Symbian OS Communications (779884), страница 67
Текст из файла (страница 67)
Although by thisstage it is too late to stop the Put command, returning an error responsecode can give an indication to the OBEX client that the Put did notcomplete successfully, and why it was unsuccessful. In the examplebelow for instance, the error returned when trying to rename the receivedfile object is passed back to the OBEX client through the err variable.TInt CObexFtpServer::PutCompleteIndication(){// Check invariants// We should always have iReceiveObject set if we’re// receiving PutCompleteIndication_LIT(KThreadName, "FTP Server");const TInt KNoReceiveObjectDefined = 1;__ASSERT_ALWAYS(iReceiveObject,User::Panic(KThreadName, KNoReceiveObjectDefined));// The Put is finished.// If the received object had a name header, we need to do a// number of things;// 1.
Get the intended file name from the object// 2. Free up the file by deleting the receive object// 3. Rename the temporary received file to its correct name// Omission - Put with empty filename does not currently// result in file deletionTInt err = KErrNone;OBEX IN SYMBIAN OS325CObexHeaderSet& hdrSet(iReceiveObject->HeaderSet());hdrSet.First();if(hdrSet.Find(KNameHeaderHi, *iHeader) == KErrNone){// The object’s header set contains a Name header, and// iHeader now points to it.//// Making some assumptions here; that the target path// and contents of the name header actually do fit in a// standard TFileName structure.//TFileName targetFileName;targetFileName.Copy(iFileSpec.DriveAndPath());targetFileName.Append(iHeader->AsUnicode());// Now we have to delete the object to free up the filedelete iReceiveObject;iReceiveObject = NULL;// Now attempt to rename the file to the target filenameerr = iFileServer.Rename(iTempFileName,targetFileName);}else{// We’ve finished with the receive object.
Free up the// memory.delete iReceiveObject;iReceiveObject = NULL;}return err;}Example 10.18 implementation ofMObexServerNotify::PutCompleteIndication()SetPutFinalResponseHeaders Some OBEX applications will go furtherthan simply using a response code, and include headers in the final Putresponse packet that provide more detailed information on the outcome ofthe Put command. This approach is supported by the Symbian OS OBEXAPIs, through GetPutFinalResponseHeaders() on the OBEX clientAPI, and through SetPutFinalResponseHeaders() on the OBEXserver API.The use of CObexServer::SetPutFinalResponseHeaders()is entirely optional, but is necessary when headers need to be sentin the final Put response packet.
As a parameter, it takes a pointerto a CObexHeaderSet that contains all the headers that the OBEXserver application wishes to return in the final Put response packet. Itis important to note that CObexServer always takes ownership of thisCObexHeaderSet, even when the function returns an error code. It canbe called at any point during a Put command, although the most usefultime to do so is generally during PutCompleteIndication(), whenthe outcome of the Put is known to the OBEX server application.326OBEXDevice with OBEX ClientTraffic "on the air"OBEX ClientSymbian device with OBEX ServerCObexServerMObexServerNotifyPut request packet()PutRequestIndication()return: CObexBufObject*:PutPacketIndication()return: TInt:Put response packet()Put request packet()PutPacketIndication()return: TInt:Put response packet()Put request packet (final)()PutPacketIndication()return: TInt:Put complete notification()return: nt:Put response packet (final)()Figure 10.8Indications to MObexServerNotify-derived class during Put commandFigure 10.8 shows the sequence of calls that occur during a typical Putoperation.Handling GetsGetRequestIndication The sequence of events upon a Get command being initiated by an OBEX client is a little more complex thanthat of a Put command.
This is because of the two-phase nature of theGet command. The object implementing MObexServerNotify is notinformed of the ongoing exchange of Get request and Get responsepackets until the specification phase is over. The specification stage mayitself contain several request–response exchanges, as can be seen inFigure 10.9.OBEX IN SYMBIAN OSDevice with OBEX ClientTraffic "on the air"OBEX Client327Symbian OS Device with OBEX ServerCObexServerMObexServerNotifyGet request packet()<Specification ObjectHeaders>Get response packet()Specification PhaseGet request packet()<Specification ObjectHeaders>Get response packet()(Final) Get request packet()<Last of SpecificationObject Headers>GetRequestIndication(aRequiredObject:CObexBaseObject)return: CObexBufObject*:GetPacketIndication()return: Tint:(Final) Get response packet()<Response ObjectHeaders>,response code "Continue"(Final) Get request packet()GetPacketIndication()return: Tint:Response PhaseGetCompleteIndication()return: Tint:(Final) Get response packet()<Last of ResponseObject Headers>,response code "Success"Figure 10.9 Indications to MobexServerNotify-derived class during Get commandUpon receiving the final Get request packet of the specificationstage of a Get command, CObexServer will call GetRequestIndication() on the MObexServerNotify-derived object passed into328OBEXCObexServer::Start().
GetRequestIndication() passes apointer to a CObexBaseObject as an argument. The CObexBaseObject in question represents the specification object transferred fromthe OBEX client, and so provides the OBEX server with the necessary information required to select the object to return to the OBEXclient during the second phase (please note that the CObexServerretains ownership of the specification object). The OBEX server application initializes a CObexBufObject to represent the object to bereturned, and then uses a pointer to this new object as a return valueto GetRequestIndication(). Once this pointer has been returned,CObexServer will proceed with the second phase of the Get commandand transfer the CObexBufObject to the OBEX client. The OBEX application retains ownership of the CObexBufObject passed as a returnvalue throughout.Please note that the specification object used by the CObexServerwill not handle body data, so the specification must be contained innon-body headers.If NULL is used as the return value of GetRequestIndication(),the Get response packet is sent to the client with a ‘Forbidden’ response.Symbian OS v9.2 will make it possible to return a wider variety ofresponse codes in this situation.CObexBufObject* CObexFtpServer::GetRequestIndication(CObexBaseObject* aRequiredObject){iTest.Printf(KObexGetIndication);CObexBufObject* objectToSend = NULL;TInt err = KErrNone;CObexHeaderSet& hdrSet(iReceiveObject->HeaderSet());hdrSet.First();if(hdrSet.Find(KTypeHeaderHi, *iHeader) == KErrNone){// The object’s header set contains a Type header, and// iHeader now points to it.//if(iHeader->AsByteSeq() == KFolderListingType()){iTest.Printf(KObexFolderListingRequest);TRAP(err, PrepareFolderListingObjectL());if(!err){objectToSend = iSendObject;}}}OBEX IN SYMBIAN OS329if(!err && (objectToSend == NULL) ){hdrSet.First();if(hdrSet.Find(KNameHeaderHi, *iHeader) == KErrNone){// The object’s header set contains a Name header,// and iHeader now points to it.// This indicates a request to fetch a file.iTest.Printf(KObexFileRequest, &(TPtrC(iHeader->AsUnicode())));HBufC* bufPtr = HBufC::New(KMaxPath+KMaxFileName);if(!bufPtr){// Couldn’t allocate buffer for filenamereturn NULL;}TPtr fileToSend = bufPtr->Des();fileToSend.Append(iFileSpec.DriveAndPath());fileToSend.Append(iHeader->AsUnicode());TRAP(err, iSendObject->SetDataBufL(fileToSend));if(!err){objectToSend = iSendObject;}delete bufPtr;}}return objectToSend;}Example 10.19 Implementation ofMObexServerNotify::GetRequestIndication()GetPacketIndication Once the MObexServerNotify-derivedobject has returned the CObexBufObject pointer, the CObexServercalls GetPacketIndication() onto the same MObexServerNotify-derived object.The GetPacketIndication() call is made for the first and everysubsequent incoming Get request packet.