Hi,
you maybe already figured it out but anyway.
First read the first 80 bytes of the incoming stream, that represents the db
header.
The header looks like this:
typedef struct
{
LocalID nextRecordListID;
UInt16 numRecords;
}
RecordListType;
// PDB Header
typedef struct
{
UInt8 name[dmDBNameLength];
UInt16 attributes;
UInt16 version ;
UInt32 creationDate;
UInt32 modificationDate;
UInt32 lastBackupDate;
UInt32 modificationNumber;
LocalID appInfoID;
LocalID sortInfoID;
UInt32 type;
UInt32 creator;
UInt32 uniqueIDSeed;
RecordListType recordList;
}
DatabaseHdrType;
Then use the date stored in this header to compare with the local db on the
receiver.
If the db should be received, pass the header to the ExgDBRead callback and
first copy from the header and if it has been read then continue reading
from the socket.
Regards,
Miro Pomsar
----- Original Message -----
From: "Dr. Vesselin Bontchev" <[EMAIL PROTECTED]>
To: "Palm Developer Forum" <[email protected]>
Sent: Saturday, April 16, 2005 21:39
Subject: Passing application-specific data during beaming
> Hello folks,
>
> I am still trying to figure out how exactly to receive whole databases
beamed to my application... I think I've almost got it, but there is
something still eluding me... Here is the problem.
>
> 1) On sysAppLaunchCmdSystemReset and sysAppLaunchCmdSyncNotify my
application registers to receive databases with a particular extension:
>
> ExgRegisterData (appCreatorID, exgRegExtensionID, "DEF");
>
> Here appCreatorID is the creator ID for my application and has been
#defined elsewhere. My application checks the PalmOS version elsewhere and
refuses to run under anything less than 3.0, so I don't need to check the OS
version here.
>
> 2) On sysAppLaunchCmdExgReceiveData I try to receive the database:
>
> Err ReceiveDatabase (ExgSocketPtr exgSocket)
> {
> LocalID dbID;
> Boolean doReset;
> Err err;
>
> err = ExgAccept (exgSocket);
> if (err == errNone)
> err = ExgDBRead (ReadDBData, DeleteProc, exgSocket, &dbID, 0,
&doReset, true);
> return err;
> }
>
> For the purpose of the exercise, ignore that I am not resetting the
device, if necessary, and that I am not checking whether the application is
running; the database in question is closed most of the time and when it is
not, the application is busy doing some work and won't accept any beaming
(or any other) events anyway.
>
> 3) The callback function ReadDBData is pretty straightforward:
>
> Err ReadDBData (void *dataP, UInt32 *sizeP, void *userDataP)
> {
> Err err;
>
> *sizeP = ExgReceive ((ExgSocketPtr) userDataP, dataP, *sizeP, &err);
> return err;
> }
>
> 4) The problem is with the callback function DeleteProc. If the database
that is being beamed to the application already exists, I want the
application to examine a particular record that contains the database
creation timestamp and, before deleting the existing database, to ask the
user for permission, if the local database is newer than the one that is
being beamed to the application. When sending the database, I stuff the
creation timestamp in the appData field of the ExgSocketType structure. Here
is how I'm trying to achieve this:
>
> Boolean DeleteProc (const Char *nameP, UInt16 version, UInt16 cardNo,
LocalID dbID, void *userData)
> {
> DmOpenRef dbRef;
> DateTimeType timeStampLocal, timeStampRemote;
> UInt32 appData;
> ExgSocketPtr socketP;
>
> dbRef = DmOpenDatabase (cardNo, dbID, dmModeReadOnly);
> if (dbRef == NULL)
> return false;
> GetDBTimeStamp (dbRef, &timeStampLocal);
> if (DmCloseDatabase (dbRef) != errNone)
> return false;
> socketP = (ExgSocketPtr) userData;
> appData = socketP->appData;
> if (TimDateTimeToSeconds (&timeStampLocal) > appData)
> {
> if (FrmAlert (kOldDatabaseAlert) != kOldDatabaseAlertYesButton)
> return false;
> }
> return (DmDeleteDatabase (cardNo, dbID) == errNone);
> }
>
> Here the function GetDBTimeStamp fetches the timestamp from the local
database. It works correctly - I have verified this with a debugger.
>
> On the sending side, I do
>
> Err BeamDatabase (void)
> {
> ExgSocketType exgSocket;
> Err err = errNone;
> LocalID dbID;
> DmOpenRef dbRef;
> DateTimeType timeStampLocal;
>
> dbID = DmFindDatabase (0, "DATABASE.DEF");
> if (dbID)
> {
> MemSet (&exgSocket, sizeof (exgSocket), 0);
> exgSocket.name = "DATABASE.DEF";
> exgSocket.description = "DATABASE.DEF";
> dbRef = DmOpenDatabase (0, dbID, dmModeReadOnly);
> if (dbRef == NULL)
> return DmGetLastErr ();
> GetDBTimeStamp (dbRef, &timeStampLocal);
> if (DmCloseDatabase (dbRef) != errNone)
> return DmGetLastErr ();
> exgSocket.appData = TimDateTimeToSeconds (&timeStampLocal);
> exgSocket.target = GetCreatorID ();
> err = ExgPut (&exgSocket);
> if (! err)
> err = ExgDisconnect (&exgSocket, ExgDBWrite (WriteDBData,
&exgSocket, exgSocket.name, dbID, 0));
> }
> else
> err = DmGetLastErr ();
> return err;
> }
>
> where the function WriteDBData is again straightforward:
>
> Err WriteDBData (const void *dataP, UInt32 *sizeP, void *userDataP)
> {
> Err err;
>
> *sizeP = ExgSend ((ExgSocketPtr) userDataP, dataP, *sizeP, &err);
> return err;
> }
>
> Again, I have verified with a debugger that the appData field is set
correctly before calling ExgPut.
>
> Well, folks, the problem is that on the receiving end (in the function
DeleteProc), the value of appData is zero. :-( Somehow, it gets lost in the
transmission and the whole check fails.
>
> Any idea what might be going wrong?
>
> Regards,
> Vesselin
> --
> For information on using the Palm Developer Forums, or to unsubscribe,
please see http://www.palmos.com/dev/support/forums/
--
For information on using the Palm Developer Forums, or to unsubscribe, please
see http://www.palmos.com/dev/support/forums/