|
1 /* |
|
2 * Copyright (c) 2005-2009 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <e32base.h> |
|
19 #include <obexconstants.h> |
|
20 |
|
21 #include "simpleObexServer.h" |
|
22 #include "simpleObexApp.h" |
|
23 #include "obexAppConstants.h" |
|
24 |
|
25 |
|
26 /** |
|
27 * Constructor. |
|
28 */ |
|
29 CObexServerHandler::CObexServerHandler(CActiveConsole* aParent) |
|
30 :iAcceptPuts(ETrue) |
|
31 { |
|
32 iParent = aParent; |
|
33 iServer = NULL; |
|
34 iObject = NULL; |
|
35 } |
|
36 |
|
37 |
|
38 |
|
39 /** |
|
40 * NewL function |
|
41 */ |
|
42 CObexServerHandler* CObexServerHandler::NewL(CActiveConsole* aParent, TTransport aTransport) |
|
43 { |
|
44 CObexServerHandler* self = new (ELeave) CObexServerHandler(aParent); |
|
45 |
|
46 CleanupStack::PushL(self); |
|
47 self->ConstructL(aTransport); |
|
48 CleanupStack::Pop(); |
|
49 return (self); |
|
50 } |
|
51 |
|
52 |
|
53 /** |
|
54 * 2nd phase constructor. This function performs the initial steps needed in |
|
55 * creating a new CObexServer object. It then creates the CObexServer object for the specified |
|
56 * transport. |
|
57 * |
|
58 */ |
|
59 void CObexServerHandler::ConstructL(TTransport aTransport) |
|
60 { |
|
61 iTransportLayer = aTransport; |
|
62 if (aTransport == EBluetooth) |
|
63 { |
|
64 // Start bluetooth socket and set security |
|
65 RSocketServ socketServ; |
|
66 socketServ.Connect(); |
|
67 RSocket listen; |
|
68 TInt test = listen.Open(socketServ, KRFCOMMDesC); |
|
69 |
|
70 if (test == KErrNone) |
|
71 { |
|
72 iParent->Console()->Printf(_L("Socket Open ... Success\n")); |
|
73 } |
|
74 |
|
75 TBTSockAddr addr; |
|
76 // Auto bind to RFComm port |
|
77 addr.SetPort(KRfcommPassiveAutoBind); |
|
78 |
|
79 TBTServiceSecurity serviceSecurity; |
|
80 |
|
81 serviceSecurity.SetUid(KUidServiceSDP); |
|
82 serviceSecurity.SetAuthentication(EFalse); |
|
83 serviceSecurity.SetEncryption(EFalse); |
|
84 serviceSecurity.SetAuthorisation(EFalse); |
|
85 serviceSecurity.SetDenied(EFalse); |
|
86 addr.SetSecurity(serviceSecurity); |
|
87 |
|
88 TInt error; |
|
89 // Set bluetooth protocol info |
|
90 TObexBluetoothProtocolInfo info; |
|
91 info.iAddr.SetPort(KObexTestPort); |
|
92 info.iTransport = KRFCOMMDesC; |
|
93 TRAP(error,iServer = CObexServer::NewL(info)); |
|
94 if (error) |
|
95 { |
|
96 iParent->Console()->Printf(_L("\r\n Could not create obex server! : error %d \r\n"),error); |
|
97 iParent->iMode = E_Inactive; |
|
98 iParent->iMode = E_Server; |
|
99 iParent->Cancel(); // cancel request for key |
|
100 } |
|
101 // Add services to the Service discovery database |
|
102 |
|
103 User::LeaveIfError(iSdp.Connect()); |
|
104 User::LeaveIfError(iSdpdb.Open(iSdp)); |
|
105 |
|
106 TSdpServRecordHandle ftphandle; |
|
107 |
|
108 iSdpdb.CreateServiceRecordL(ftpUuid, ftphandle); |
|
109 iSdpdb.UpdateAttributeL(ftphandle, KSdpAttrIdServiceName, KServerDesC); |
|
110 |
|
111 iProtDescList = CSdpAttrValueDES::NewDESL(0); |
|
112 |
|
113 iProtDescList |
|
114 ->StartListL() |
|
115 ->BuildDESL() |
|
116 ->StartListL() |
|
117 ->BuildUUIDL(KL2CAPUUID) |
|
118 ->EndListL() |
|
119 ->BuildDESL() |
|
120 ->StartListL() |
|
121 ->BuildUUIDL(KRfcommUuid) |
|
122 ->BuildUintL(TSdpIntBuf<TInt8>(KObexTestPort)) |
|
123 ->EndListL() |
|
124 ->BuildDESL() |
|
125 ->StartListL() |
|
126 ->BuildUUIDL(KObexProtocolUuid) |
|
127 ->EndListL() |
|
128 ->EndListL(); |
|
129 // Update attribute |
|
130 iSdpdb.UpdateAttributeL(ftphandle, KProtocolDescriptorListUUID, *iProtDescList); // put into both records |
|
131 delete iProtDescList; |
|
132 |
|
133 User::LeaveIfError(listen.Bind(addr)); |
|
134 |
|
135 TInt queueSize=2; |
|
136 User::LeaveIfError(listen.Listen(queueSize)); |
|
137 |
|
138 iParent->Console()->Printf(_L("\n.....Now Listening.....\n")); |
|
139 |
|
140 } |
|
141 |
|
142 else if (aTransport == EIrda) |
|
143 { |
|
144 |
|
145 //creating the transport info |
|
146 TObexIrProtocolInfo transportInfo; |
|
147 transportInfo.iAddr.SetPort(KAutoBindLSAP);//default obex server for now |
|
148 transportInfo.iTransport = KObexIrTTPProtocol; |
|
149 transportInfo.iClassName = KIrdaClassName; |
|
150 transportInfo.iAttributeName = KIrdaTransportAttrName; |
|
151 |
|
152 iServer = CObexServer::NewL (transportInfo); |
|
153 |
|
154 } |
|
155 |
|
156 else if (aTransport == EWin32Usb) |
|
157 { |
|
158 // Create transport info |
|
159 TObexUsbProtocolInfo aInfo; |
|
160 aInfo.iTransport = KObexWin32UsbProtocol; |
|
161 aInfo.iInterfaceStringDescriptor = KServerInterfaceDescriptor; |
|
162 iServer = CObexServer::NewL (aInfo); |
|
163 |
|
164 } |
|
165 |
|
166 // Now that the transport has been selected and Obex Server started |
|
167 // We need to do some initialisation with Obex Objects so that we are |
|
168 // prepared to deal with Put/Get requests from the client |
|
169 |
|
170 iObject = CObexBufObject::NewL (NULL); |
|
171 |
|
172 iBuf = CBufFlat::NewL(KServerBufExpandSize); |
|
173 |
|
174 iBuf->ResizeL(KServerBufExpandSize);// Resize the buffer |
|
175 |
|
176 iObject = CObexBufObject::NewL(NULL); |
|
177 iObject->SetDataBufL(iBuf); |
|
178 //Create the RFile to be used |
|
179 User::LeaveIfError(iFs.Connect()); |
|
180 User::LeaveIfError(iFs.CreatePrivatePath(EDriveC)); |
|
181 User::LeaveIfError(iFs.SetSessionToPrivate(EDriveC)); |
|
182 User::LeaveIfError(iFs.SessionPath( iSessionPath )); |
|
183 // Start the server |
|
184 User::LeaveIfError(iServer->Start (this)); |
|
185 |
|
186 } |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 /** |
|
192 * This function stops the OBEX server |
|
193 */ |
|
194 void CObexServerHandler::Stop() |
|
195 { |
|
196 if (iServer) |
|
197 { |
|
198 iServer->Stop(); |
|
199 } |
|
200 } |
|
201 |
|
202 |
|
203 /** |
|
204 * Destructor. |
|
205 */ |
|
206 CObexServerHandler::~CObexServerHandler () |
|
207 { |
|
208 Stop(); |
|
209 |
|
210 iSdpdb.Close(); |
|
211 iSdp.Close(); |
|
212 |
|
213 delete iObject; |
|
214 delete iBuf; |
|
215 delete iServer; |
|
216 } |
|
217 |
|
218 /** |
|
219 * This function enables authentication on the OBEX server. |
|
220 * The password is defined in source. |
|
221 */ |
|
222 void CObexServerHandler::EnableAuthenticationL() |
|
223 { |
|
224 iChallengePassword = KAuthPassword; |
|
225 iServer->SetChallengeL(iChallengePassword); |
|
226 iIsAuthenticationEnabled = ETrue; |
|
227 } |
|
228 |
|
229 /** |
|
230 * This function disables authentication on the server. |
|
231 */ |
|
232 void CObexServerHandler::DisableAuthentication() |
|
233 { |
|
234 iServer->ResetChallenge(); |
|
235 iIsAuthenticationEnabled = EFalse; |
|
236 } |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 // MObexServerNotify interface functions |
|
243 |
|
244 /** |
|
245 * Called if an OBEX protocol error occurs. |
|
246 */ |
|
247 void CObexServerHandler::ErrorIndication (TInt aError) |
|
248 { |
|
249 iParent->Console()->Printf(_L("Obex Server error %d"), aError); |
|
250 } |
|
251 |
|
252 /** |
|
253 * Called when the underlying transport connection is made from a remote client to the server. |
|
254 */ |
|
255 void CObexServerHandler::TransportUpIndication () |
|
256 { |
|
257 iParent->Console()->Printf(_L("\nTransport started\n")); |
|
258 } |
|
259 |
|
260 /** |
|
261 * Called when the transport connection is dropped (by either party). |
|
262 */ |
|
263 void CObexServerHandler::TransportDownIndication () |
|
264 { |
|
265 iParent->Console()->Printf(_L("\nTransport down\n")); |
|
266 } |
|
267 |
|
268 /** |
|
269 * Called when an OBEX connection is made from a remote client. |
|
270 */ |
|
271 TInt CObexServerHandler::ObexConnectIndication(const TObexConnectInfo& aRemoteInfo, const TDesC8& /*aInfo*/) |
|
272 { |
|
273 |
|
274 iParent->Console()->Printf(_L("\r\nCObexServerHandler::ObexConnectIndication")); |
|
275 iParent->Console()->Printf(_L("\r\nConnected to machine with OBEX version %d.%d\r\n"), |
|
276 aRemoteInfo.VersionMajor (), aRemoteInfo.VersionMinor ()); |
|
277 |
|
278 return (KErrNone); |
|
279 |
|
280 } |
|
281 |
|
282 /** |
|
283 * Called on a (graceful) OBEX disconnection by the client. |
|
284 */ |
|
285 void CObexServerHandler::ObexDisconnectIndication (const TDesC8& /*aInfo*/) |
|
286 { |
|
287 iParent->Console()->Printf(_L("\r\nObex Disconnected\r\n\r\n")); |
|
288 } |
|
289 |
|
290 |
|
291 /** |
|
292 * Called on receipt of the first packet of a (valid) put request. |
|
293 */ |
|
294 CObexBufObject* CObexServerHandler::PutRequestIndication () |
|
295 { |
|
296 iParent->Console()->Printf(_L("Receiving object...\r\n")); |
|
297 iObject->Reset (); |
|
298 |
|
299 if ( iAcceptPuts) |
|
300 return (iObject); |
|
301 else |
|
302 return (NULL); |
|
303 } |
|
304 |
|
305 /** |
|
306 * Called on receipt of every packet of an OBEX PUT operation. |
|
307 */ |
|
308 TInt CObexServerHandler::PutPacketIndication () |
|
309 { |
|
310 |
|
311 TUint length = iObject->Length(); |
|
312 |
|
313 TUint received = iObject->BytesReceived(); |
|
314 TUint8 percent = 0; |
|
315 if (length > 0) |
|
316 { |
|
317 percent = TUint8((100 * received) / length); |
|
318 iParent->Console()->Printf(_L("\r%d %% "), percent); |
|
319 } |
|
320 else |
|
321 { |
|
322 iParent->Console()->Printf(_L("\r%d "), iObject->BytesReceived ()); |
|
323 } |
|
324 return (KErrNone); |
|
325 |
|
326 } |
|
327 |
|
328 /** |
|
329 * Called after the final put packet has been successfully received and parsed. |
|
330 */ |
|
331 TInt CObexServerHandler::PutCompleteIndication () |
|
332 { |
|
333 TPtrC name=iObject->Name(); |
|
334 TBuf<100> type; |
|
335 type.Copy(iObject->Type()); |
|
336 iParent->Console()->Printf(_L("\r\nSuccessfully received '%S'\r\nType[%d]: '%S'\r\n"), &name, type.Length(), &type); |
|
337 |
|
338 TInt err = KErrNone; |
|
339 TBuf<80> filename(iSessionPath); |
|
340 filename.Append(iObject->Name()); |
|
341 err = iObject->WriteToFile(filename); |
|
342 if (err == KErrAlreadyExists) |
|
343 { |
|
344 iParent->Console()->Printf(_L("\r\nWrite failed, File Already Exists\n")); |
|
345 } |
|
346 |
|
347 iObject->Reset (); |
|
348 return (err); |
|
349 } |
|
350 |
|
351 |
|
352 /** |
|
353 * Called when a full get request has been received from the client. |
|
354 */ |
|
355 CObexBufObject* CObexServerHandler::GetRequestIndication (CObexBaseObject* aRequiredObject) |
|
356 { |
|
357 |
|
358 TRAPD(err,SetUpGetObjectL(aRequiredObject)); |
|
359 if (err != KErrNone) |
|
360 { |
|
361 iParent->Console()->Printf(_L("\nSetUpGetObjectL() returned %d.\n"), err); |
|
362 return NULL; |
|
363 } |
|
364 |
|
365 return (iObject); |
|
366 |
|
367 } |
|
368 |
|
369 |
|
370 /** |
|
371 * Called for every packet of get reply sent by the server back to the client. |
|
372 */ |
|
373 TInt CObexServerHandler::GetPacketIndication () |
|
374 { |
|
375 if (iObject->Length () > 0) |
|
376 iParent->Console()->Printf(_L("\r%d %% "), |
|
377 100 * iObject->BytesSent () / iObject->Length ()); |
|
378 else |
|
379 iParent->Console()->Printf(_L("\r%d Bytes "), iObject->BytesSent ()); |
|
380 return (KErrNone); |
|
381 } |
|
382 |
|
383 /** |
|
384 * Called when the final packet of the object has been returned to the client. |
|
385 */ |
|
386 TInt CObexServerHandler::GetCompleteIndication () |
|
387 { |
|
388 iParent->Console()->Printf(_L("Obex Get Complete\r\n")); |
|
389 iObject->Reset (); |
|
390 return (KErrNone); |
|
391 } |
|
392 |
|
393 |
|
394 |
|
395 /** |
|
396 * Called when an OBEX SETPATH command is received by the server. |
|
397 * |
|
398 */ |
|
399 TInt CObexServerHandler::SetPathIndication (const CObex::TSetPathInfo& aPathInfo, const TDesC8& /*aInfo*/) |
|
400 { |
|
401 iParent->Console()->Printf(_L("Obex SetPath request:\r\n")); |
|
402 iParent->Console()->Printf(_L(" --- Flags = '%d' - Constants = '%d' - "), aPathInfo.iFlags, aPathInfo.iConstants); |
|
403 |
|
404 if (aPathInfo.iNamePresent) |
|
405 iParent->Console()->Printf(_L("Name = %S\r\n"), &aPathInfo.iName); |
|
406 else |
|
407 iParent->Console()->Printf(_L("> No Name Present <\r\n")); |
|
408 |
|
409 iParent->Console()->Printf(_L("\nReturning success...!\n")); |
|
410 return (KErrNone); |
|
411 |
|
412 } |
|
413 |
|
414 /** |
|
415 * Called when an abort packet is received from the client. |
|
416 */ |
|
417 void CObexServerHandler::AbortIndication () |
|
418 { |
|
419 iParent->Console()->Printf(_L("Obex Operation aborted\r\n")); |
|
420 if(iObject) |
|
421 { |
|
422 // Determine if we have recieved any amount of the object |
|
423 // Return without notifing user if we haven't. |
|
424 if(!iObject->BytesReceived()) |
|
425 return; |
|
426 iParent->Console()->Printf(_L("\r\nWe have received part of an Obex object\r\n\r\n")); |
|
427 |
|
428 iObject->Reset(); |
|
429 } |
|
430 } |
|
431 |
|
432 |
|
433 /** |
|
434 * This is the function that sets up an object ready for a Get. |
|
435 * It takes as a parameter the requested object and then examines it's |
|
436 * name and if a filename matches then the object it setup from that file. |
|
437 */ |
|
438 void CObexServerHandler::SetUpGetObjectL(CObexBaseObject *aRequestedObject) |
|
439 { |
|
440 // Get the name of the requested object |
|
441 TBuf<200> name (aRequestedObject->Name ()); |
|
442 if(name.Length()) |
|
443 { |
|
444 iParent->Console()->Printf(_L("Obex Get Request for name '%s'\r\n"), name.PtrZ ()); |
|
445 } |
|
446 |
|
447 else |
|
448 { |
|
449 iParent->Console()->Printf(_L("Obex Get Request unknown details\r\n")); |
|
450 User::Leave(KErrNotSupported); |
|
451 } |
|
452 iObject->Reset(); |
|
453 |
|
454 RFs fs; |
|
455 RFile f; |
|
456 // Attempt to open the specified file |
|
457 if ((fs.Connect () != KErrNone) || |
|
458 (f.Open (fs, name, EFileShareReadersOnly | EFileRead) != KErrNone)) |
|
459 { |
|
460 iParent->Console()->Printf(_L("\r\nError reading '%S'."), &name); |
|
461 User::Leave(KErrNotFound); |
|
462 } |
|
463 // We can now proceed in setting up the object using the file retrieved |
|
464 |
|
465 TInt size = 0; |
|
466 // Set size of file |
|
467 User::LeaveIfError(f.Size (size)); |
|
468 // Resize buffer object |
|
469 iBuf->ResizeL(size); |
|
470 // Get a pointer to represent the data |
|
471 TInt bufStart=0; |
|
472 TPtr8 data (iBuf->Ptr(bufStart)); |
|
473 // Read data from file, |
|
474 f.Read (data); |
|
475 if (iBuf->Size() < size) |
|
476 User::Leave(KErrGeneral); |
|
477 // Set name of the object |
|
478 iObject->SetNameL(name); |
|
479 // Set length |
|
480 iObject->SetLengthL(size); |
|
481 TTime time; |
|
482 if (f.Modified(time) == KErrNone) |
|
483 iObject->SetTimeL(time); |
|
484 } |