The Short Message Service (SMS) is a protocol designed to transmit short alpha-numeric messages via a dedicated cellular provider's "service center." SMS is built into the GSM (Global System for Mobile communications) standard that has gained general acceptance within Europe; SMS will also most likely be integrated into whatever digital cellular network becomes the de-facto standard within the United States.
The Nokia 9000i Communicator is compliant with the transmission and reception of SMS protocol messages according to the GSM standard. With SMS, it is possible to create applications and services that request and retrieve short text messages (up to 160 characters) to any server or user on the GSM network. The ability to send and receive short messages can enable a wide variety of services. For example, short messages can be used to retrieve stock quotes, place horse-racing bets at a paramutual facility, or play chess with another member of the GSM network. The possible uses for the SMS protocol are almost limitless. A service need only be connected to the GSM network.
Geoworks' Mailbox library includes built-in transmission and receipt of SMS messages. The elements of the Mailbox library that are of concern to SMS application developers have been excerpted and included in this chapter.You will not need to understand the inner workings of the Mailbox library to write an SMS application or service.
Before reading this chapter, you should be familiar with cellular technologies, the SMS standard and elementary GEOS programming--in particular, the use of GEOS Virtual Memory (VM) files.
1 SMS OverviewThe Short Message Service protocol handles a "short message" of up to 160 characters. The SMS standard of 160 characters allows you to send a text message to any single node (address) on the GSM network by way of a dedicated cellular service provider.
The cellular service provider is responsible for managing incoming SMS messages and holding them until the recipient's phone becomes active. The length of time that an SMS message should be held can be specified by the sending party. This is known as a validity period .
The cellular provider may also elect to deliver the message in a format other than SMS. This is done at the server through a message conversion into the alternative format (e.g., as a fax message, as an email, as a page, etc.) This alternative method of delivery may also be specified by the sending party (though, of course, the recipient must have the means to handle such a format).
Because the SMS message is so short, it is guaranteed to be delivered as a single packet of information.
The Nokia 9000i Communicator comes with built-in capabilities to send and receive SMS messages. This is enabled through use of Geoworks' Mailbox library. Because the Mailbox library includes all Inbox/Outbox functionality (email, faxing, etc.), it contains a large amount of information that is not relevant to an SMS service developer. This section will only detail general information about the Mailbox library and API specific to SMS application developers.
The purpose of the Mailbox library is to let applications send and receive information to and from other computers, through a variety of communications media. The mailbox insulates the application as much as possible from the mechanics of transmitting and receiving the information.
In order to use the Mailbox library, an application must package information in a format acceptable to both a data driver (which stores the message) and a transport driver (which sends the message) -- in this case the SMS transport driver. The application then registers this message with the Mailbox library. During the registration process, you specify in which data format the message is stored.
The Mailbox library stores messages that have not yet been transmitted in its outbox . Messages are held in the outbox until the hardware connection necessary for transmission is available. An application can also specify that a message not be delivered until a specific time. In this case, the message will automatically remain in the outbox until that time. While a message is in the outbox, the device's user can examine information about the message and delay or even cancel its delivery.
When the time comes to send the message, the Mailbox library activates the appropriate transport driver. This activation is transparent to an application developer.
There are three pieces of information that you will need to know when you send an SMS message. These are rather self-evident:
If you wish the SMS message to be sent to a particular application on the receiving Nokia 9000i Communicator, you will also need the following information:
TokenChars
) of the receiving app.
ManufacturerID
of the receiving app.
In GEOS, these two pieces of information are referred to as a
GeodeToken
. If the application is your own, the
GeodeToken
is easy enough to determine (since you will have defined it yourself). If the application is not your own, you will need to contact that manufacturer or cellular provider for this information.
Sending and the Mailbox Library
Any SMS message that is sent out to the cellular provider is routed through the mailbox's outbox . There are three basic paradigms involved in packaging up information for use by the outbox. Although knowledge of how they work is not essential to sending an SMS message, it may be important when troubleshooting problems.
Apart from any parameters sent to the mailbox, the three basic pieces of information the outbox needs to know in order to send a message are:
When a message is placed in the outbox, the mailbox calls the appropriate data driver to store the data. When a connection is made, the mailbox calls the appropriate transport driver and sends the message. Note that the mailbox itself does not need to know the message's contents, or even its format.
mailbox.goh
To send an SMS message to the outside world, an application will need to perform the following steps:
GeoworksMailboxDataFormatID
), but a VM file is the easiest to manipulate. This VM file will be accessed by a Mailbox data driver. (See Storing the Text Within a VM File
.)
SMSendingOptions
parameters in a DB item. These will be used by the SMS transport driver when the message is delivered. (See Setting Up the SMSending Options
.)
MailboxRegisterMessageArgs
structure. (See Setting Up the MailboxRegisterMessageArgs
.)
MailboxRegisterMessage()
. (See Registering the Message
.)These steps are detailed in the sections following.
foam.goh
The Short Message Service protocol is able to handle a "short message" of up to 160 characters. The Foam library defines this character limit:
#define FOAM_MAX_SMS_TEXT_SIZE 160
The Nokia 9000i Communicator also allows you to further specify a particular application within the Nokia 9000i Communicator by adding a prefix to the SMS message (thus reducing the amount of useful text).
This prefix consists of two backslashes ("//"),
a 4-byte GEOS application token ( TokenChars),
a 5-byte GEOS ManufacturerID,
and a carriage return ("/r", ASCII 13, or 0x0D hex).
The Mailbox library will correctly read all characters up to the carriage return.
For example:
//SKAA11\r
is a valid prefix.
The application
TokenChars
and
ManufacturerID
should match those of the intended
receiving
application. If you define your own application, and only wish to communicate with its counterpart running on another device, you will define this string in the application's
.gp
file. The string is constructed from the
tokenchars
and
tokenid
lines of the
.gp
file.
You may also send a message to a different application, as long as you know its
TokenChars
and
ManufacturerID
.
This prefix should leave at least 148 characters to store the alpha-numeric text message. When concatenating two strings, be sure that you do not overflow the bounds of the array.
Code Display 3-1 Setting Up an SMS Text Message
/* * Declare the buffer to store the text message and write the prefix to the buffer. */ TCHAR smsMessage[FOAM_MAX_SMS_TEXT_SIZE + 1] = "//SKAA11\r"; TCHAR smsText[] = "Here's my test message. I better make sure it fits.";
/*
* Add the body of the text to the buffer but first check the bounds.
*/
if ( strlen( smsMessage ) + strlen( smsText ) <= FOAM_MAX_SMS_TEXT_SIZE )
{
strcat( smsMessage, smsText );
}
MailboxGetVMFile(), Mailbox\vmtree.goh
Text within an SMS message needs to be stored by the Mailbox until it connects with a cellular service provider. When you register a message with the Mailbox library, you indicate what storage format you have selected. The Mailbox uses a data driver to store and retrieve messages. There are a number of data drivers available, but we only need to know a few.
SMS messages may either be stored as VM (Virtual Memory) trees or as GEOS files, within the Mailbox itself. VM trees offer a lower overhead, and are simpler to use, so that is the format we have documented. (It is possible that future data drivers will become available as well.) If you are unfamiliar with GEOS VM trees, consult the Virtual Memory chapter of the Concepts book.
The mailbox data driver stores its data in what is called a VM tree. This tree is referenced by a
VMTreeAppRef
structure.
typedef struct {
VMChain VMTAR_vmChain;
VMFileHandle VMTAR_vmFile;
} VMTreeAppRef;
VMTAR_vmChain
stores the
VMChain
to pass to the data driver. For SMS messages, simply use the VMCHAIN_MAKE_FROM_VM_BLOCK macro to construct a
VMChain
from a single
VMBlockHandle
.
vmFile
stores the
VMFileHandle
which contains the VM block.The Mailbox stores these VM trees locally within an administation file that it maintains. To store the text within a Mailbox-compatible VM file, perform the following steps:
MailboxGetVMFile()
to retrieve a VM file handle within the Mailbox. This routine expects an argument indicating the expected number of blocks to be added to the file; because the SMS message can be contained in a single block, pass 1. Also pass a buffer to store the returned
VMStatus.
VMFileHandle.
VMAlloc().
VMLock(). This routine returns the segment address of the locked block. You will also receive a temporary memory handle that you can use to manipulate the block.
VMChainLink
that begins the block.)
VMDirty().
VMUnlock().
VMTreeAppRef
structure. This format is understood by the mailbox data driver.Code Display 3-2 Storing the Text In a VM File
VMFileHandle vmFile; VMBlockHandle vmBlock; TCHAR *textPtr; MemHandle mh; word vmStatus; VMTreeAppRef vmRef;
/* * Obtain the handle of a writable VM file from the Mailbox library. We pass one * since we do not plan to add additional blocks to this file (because SMS messages * are so short). */ vmFile = MailboxGetVMFile(1, &vmStatus);
/* * Allocate a VM block and store the text within this block. The block will need * to fit a header (VMChainLink), the SMS message itself, and a null terminator. */ vmBlock = VMAlloc(vmFile, (sizeof(VMChainLink) + strlen(smsMessage) +1), 0); charPtr = VMLock(vmFile, vmBlock, &mh);
/* * We advance past the VMChainLink contained at the beginning of the VM * block and copy the text to that location. */ strcpy(textPtr + sizeof(VMChainLink), smsMessage);
/* * Dirty the block and unlock it. */ VMDirty(mh); VMUnlock(mh);
/* * Store the VM file and VM block within a VMTreeAppRef structure. This is the * format that the mailbox library understands. Essentially, it ia a VM "chain" * of a single VM file. */ vmRef.VMTAR_vmChain = VMCHAIN_MAKE_FROM_VM_BLOCK(vmBlock); vmRef.VMTAR_vmFile = vmFile;
MailboxGetAdminFile(), smdefine.goh, SMSendingOptions, ReadCSNumberFromIniFile()
When registering a mailbox message, the application must specify a data driver to use when storing the message. It will also need to specify which transport driver to use when the message is to be delivered. The GEOS SMS transport driver expects a number of parameters indicating how the SMS message should be sent. These parameters are passed as a
SMSendingOptions
structure within a GEOS
DBItem.
To store these parameters within a compatible DB item, perform the following steps:
MailboxGetAdminFile()
to retrieve the
VMFileHandle
of the Mailbox administration file. This is where you will copy your SMS parameters.
DBAllocUngrouped().
DBLockUngrouped().
SMSendingOptions
parameters into this DB item.
InitFileReadStringBuffer(). Copy that number into the DB item.
DBDirty().
DBUnlock().
The
SMSendingOptions
structure is defined within
smdefine.goh
and is shown below:
typedef struct {
SMReplyPath SMSO_replyPath;
SMValidityPeriod SMSO_validityPeriod;
SMMessageConversion SMSO_messageConversion;
TCHAR SMSO_scAddress[MAX_ADDRESS_SIZE];
} SMSendingOptions;
#define MAX_ADDRESS_SIZE 22
replyPath
contains an
SMReplyPath
value which indicates whether the recipient may reply to the message through the sender's service provider. Possible values are:
_validityPeriod
contains an
SMValidityPeriod
value which indicates the length of time that the message is considered valid for delivery. The cellular provider should interpret this value and if it is unable to connect with the recipient, drop the message and inform the sender that the message was not delivered. Possible values are:
messageConversion
contains an
SMMessageConversion
value, indicating that you wish to have the SMS message delivered to the recipient in a different format than that of an SMS message (provided that the cellular provider offers this service). Possible values are:
scAddress
stores the address of the service center (cellular provider). This number is stored as an ASCII text string and is limited to 22 characters. This number should be retrieved from the Nokia 9000i Communicator's .INI file; the number is stored under the
scNumber
field within the
SMS
category. This "address" in this case is really just a numerical phone number.initfile.h, InitFileReadStringBuffer()
To read a string from the .INI file, call
InitFileReadStringBuffer()
. Pass "SMS" as the category and "scNumber" as the key. The routine will read the entry into a buffer passed to the routine. It will also read the size of the string into another buffer.
Code Display 3-3 Setting the SMSendingOptions Parameters
SMSendingOptions *ptrSendingOptions VMFileHandle adminFile; DBGroupAndItem smsParams; word sizeOfBuffer;
adminFile = MailboxGetAdminFile();
smsParams = DBAllocUngrouped(adminFile, sizeof(SMSendingOptions));
ptrSendingOptions = (SMSendingOptions *) DBLockUngrouped(adminFile, smsParams);
/* set desired sending options */ ptrSendingOptions->SMSO_replyPath = SMRP_NO; ptrSendingOptions->SMSO_validityPeriod = SMVP_24_HOURS; ptrSendingOptions->SMSO_messageConversion = SMMC_NORMAL;
/* be sure to initialize these fields as well, otherwise the app will crash! */ ptrSendingOptions->SMSO_dataCodingScheme = 0; ptrSendingOptions->SMSO_userDataLength = 0; ptrSendingOptions->SMSO_userDataLength = 0;
InitFileReadStringBuffer("SMS",
"scNumber",
ptrSendingOptions->SMSO_scAddress,
0,
&sizeOfBuffer);
DBDirty(ptrSendingOptions); DBNUnlock(ptrSendingOptions);
MailboxRegisterMessageArgs, MailboxTransAddr
By now, you have created a reference to the SMS message itself (within a
VMTreeAppRef
structure); you have also placed the SMS sending parameters within the mailbox administration file. You are now ready to load the
MailboxRegisterMessageArgs
structure with parameters. (Two of these parameters will be the location of the SMS message and its sending parameters.)
SMSendingOptions
are located.
All of these steps are accomplished by simply filling in a
MailboxRegisterMessageArgs
structure. This structure is large, but it is not altogether complicated. Each field is described in the following sections, though only SMS relevant information is shown. It is shown below:
typedef struct {
MailboxStorage MRA_bodyStorage;
MailboxDataFormat MRA_bodyFormat;
const void *MRA_bodyRef;
word MRA_bodyRefLen;
MailboxTransport MRA_transport;
MailboxTransportOption MRA_transOption;
MailboxTransAddr *MRA_transAddrs;
word MRA_numTransAddrs;
dword MRA_transData;
MailboxMessageFlags MRA_flags;
const char *MRA_summary;
GeodeToken MRA_destApp;
FileDateAndTime MRA_startBound;
FileDateAndTime MRA_endBound;
} MailboxRegisterMessageArgs;
As we mentioned, the Mailbox will need to store a message in a format that it can understand. Rather than have the Mailbox understand every data format that is (or will ever be) developed, it is easier to "package" the message in a small number of standard formats. You specify in what format the message will be wrapped in the MRA
_bodyStorage
field.
bodyStorage
indicates under what format (of type
MailboxStorage
) the message will be stored in the internal Mailbox administration file.
MailboxStorage
is defined as follows:typedef struct {
word MS_id;
ManufacturerID MS_manuf;
} MailboxStorage;
MS_id
GeoworksMailboxStorageID. The following types are valid:GMSID_FILE GMSID_VM_TREE
MS_manuf
ManufacturerID
of the data driver being used. Since we will be using Geoworks VM trees, we will store MANUFACTURER_ID_GEOWORKS in this location.MRA_bodyFormat
MailboxDataFormat
. This is defined below:typedef struct {
word MDF_id;
ManufacturerID MDF_manuf;
} MailboxDataFormat;
MDF_id
GeoworksMailboxDataFormatID. Pass GMDFID_SHORT_MESSAGE in this field
to indicate that the message is a Geoworks SMS message.MDF_manuf
ManufacturerID
of the format. Since we will be using Geoworks SMS , we will
store MANUFACTURER_ID_GEOWORKS in this location.
_bodyRef
stores a pointer to the reference of the SMS message. Since we will be storing the message in a VM tree, we will reference that message with a
VMAppTreeRef
.
bodyRefLen
stores the length of the reference indicated in MRA_
bodyRef
. In this case, we will store the size of the
VMAppTreeRef
structure.
transport
field.
_transport
takes an argument of type
MailboxTransport
. This is defined below:typedef struct {
word MT_id;
ManufacturerID MT_manuf;
} MailboxTransport;
MT_id
GeoworksMailboxTransportID. MT_manuf
ManufacturerID
of the transport driver being used. Since we will be using Geoworks SM transport driver, we will store MANUFACTURER_ID_GEOWORKS in this location.MRA_transOption
MRA_transAddrs
MailboxTransAddr
structure; it is only important that the transport driver understand the format for this address.
MailboxTransAddr
structures. This structure is defined below:typedef struct {
const void *MTA_transAddr;
unsigned MTA_transAddrLen;
const char *MTA_userTransAddr;
} MailboxTransAddr;
MTA_transAddrMTA_transAddrLenMTA_transAddr.MTA_userTransAddrMTA_transAddr.MRA_numTransAddrsMRA_transAddrs.MRA_transData
DBItem
containing a structure of type
SMSendingOptions
.MRA_flags
MailboxMessageFlags. MRA_summaryMRA_destApp
GeodeToken
of the destination application.MRA_startBound
FileDateAndTime
) to begin transmission of the message. You may also pass the value MAILBOX_NOW (0) for immediate delivery.MRA_endBound
FileDateAndTime
) to end attempts to transmit the message to the service provider. You may also pass the value MAILBOX_ETERNITY (-1) to indicate attempt until successful.Code Display 3-4 Setting Up the Mailbox Registration Arguments
MailboxRegisterMessageArgs registerArgs; MailboxTransAddr addressList; TCHAR number[MAX_ADDRESS_SIZE]
/* * We tell the mailbox that the data is stored within a VMTreeAppRef. */ registerArgs.MRA_bodyStorage.MS_id = GMSID_VM_TREE; registerArgs.MRA_bodyStorage.MS_manuf = MANUFACTURER_ID_GEOWORKS;
/* * We tell the mailbox that this is an SMS message. */ registerArgs.MRA_bodyFormat.MDF_id = GMDFID_SHORT_MESSAGE; registerArgs.MRA_bodyFormat.MDF_manuf = MANUFACTURER_ID_GEOWORKS;
/* * We tell the mailbox where the body text is stored. */ MRA_bodyRef = &vmRef; registerArgs.MRA_bodyRefLen = sizeof(VMTreeAppRef);
/* * We tell the mailbox to use the SM transport driver when sending the message. */ registerArgs.MRA_transport.MT_id = GMTID_SM; registerArgs.MRA_transport.MT_manuf = MANUFACTURER_ID_GEOWORKS;
registerArgs.MRA_transOption = 0;
/* * Normally, we would retrieve the phone number from an outside source (such as * the contact database). Here, we just set it to a specific value. */
number = "13125551212";
/* * We need to stuff each address (in this case, a phone number) into a * MailboxTransAddr structure. */
addressList.MTA_transAddr = &number; addressList.MTA_transAddrLen = strlen(number); addressList.MTA_userTransAddr = &number;
registerArgs.MRA_transAddrs = &addressList; registerArgs.MRA_numTransAddr = 1;
/* * We pass the previously set up SMSendingOptions in the DBGroupItem to the * transport driver. */ registerArgs.MRA_transData = smsParams;
registerArgs.MRA_flags = MMF_DELETE_BODY_AFTER_TRANSMISSION;
registerArgs.MRA_summary = "Chess Move";
strcpy(registerArgs.MRA_destApp.GT_chars, "SKAA"); registerArgs.MRA_destApp.GT_manufID = MANUFACTURER_ID_NOKIA;
registerArgs.MRA_startBound = MAILBOX_NOW; registerArgs.MRA_endBound = MAILBOX_ETERNITY;
MailboxRegisterMessage(), MailboxDoneWithVMFile()
Finally, you have everything set up. To send the message, all you need to do is register the message with the mailbox library.
MailboxRegisterMessage()
takes an address (of type
MailboxMessage
) as a second parameter. The routine will write a token value into this address so that future mailbox routines can refer to this message by its token.
Do not confuse this token with the actual message (which is sent through the
MailboxRegisterMessageArgs
).
After you have successfully registered the message, call
MailboxDoneWithVMFile()
to tell the mailbox to get rid of the temporary VM file it had created.
Code Display 3-5 Using MailboxRegisterMessage
MailboxRegisterMessageArgs registerArgs; MailboxMessage msgToken; MailboxError mailboxError; VMFileHandle vmFile;
mailboxError = MailboxRegisterMessage(®isterArgs, &msgToken);
if (mailboxError == ME_SUCCESS) {
/* If we want to do anything special upon success, here it would reside ... */
};
MailboxDoneWithVMFile(vmFile);
There is a possibility that
MailboxRegisterMessage()
may return an error (of type
MailboxError
) if something is not working correctly (or if the message was not set up correctly). The routine returns ME_SUCCESS if the registration was successful.
The following are valid mailbox error codes:
ME_SUCCESS = 0 ME_NOT_ENOUGH_MEMORY ME_CANNOT_LOAD_DATA_DRIVER ME_CANNOT_LOAD_TRANSPORT_DRIVER ME_UNABLE_TO_CREATE_TRANSMIT_THREAD ME_CANNOT_ENQUEUE_MESSAGE ME_USER_CANCELED ME_LOST_CONNECTION ME_CANNOT_CREATE_MESSAGE_FILE ME_CANNOT_RESIZE_MBOX_REF ME_CANNOT_SAVE_MESSAGE_FILE ME_CANCELLED_BY_RECEIVER ME_MESSAGE_BLOCKS_ARE_MISATCHED ME_DATA_DRIVER_CANNOT_STORE_MESSAGE_BODY ME_INSUFFICIENT_DISK_SPACE ME_CANNOT_CONNECT
The following are unrecoverable
MailboxError
error codes. (The high bit is set if this is the case.)
#define ME_UNRECOVERABLE 0x8000
ME_ADDRESS_INVALID ME_DATA_DRIVER_CANNOT_ACCESS_MESSAGE_BODY ME_UNSUPPORTED_BODY_FORMAT ME_MESSAGE_BODY_INVALID ME_INVALID_MESSAGE ME_REPLY_ADDRESS_NOT_AVAILABLE ME_DESTINATION_APPLICATION_UNKNOWN ME_UNKNOWN_DISK_ERROR ME_APP_REF_BUF_TOO_SMALL ME_CANNOT_OPEN_MESSAGE_FILE ME_CANNOT_READ_MESSAGE_FILE ME_CAN_NEVER_CONNECT
There are two ways the Nokia 9000i Communicator may receive an SMS message: standard, or targeted.
As a developer, you do not need to concern yourself with standard messages since a "standard" message is handled by the Nokia 9000i Communicator's built-in SMS application. This application handles standard messages that are either sent without an SMS prefix or that are sent specifically to the SM Receive application.
Targeted messages are those messages sent using the twelve character prefix.
These messages may not necessarily be sent using another Nokia 9000i Communicator; any device that uses the correct SMS prefix can contact a specific application if it so desires. In any case, the twelve character prefix (containing the GeodeToken
) will specify the application that is meant to receive the message.
SM Receive and the Mailbox Library
When the GSM network informs the unit that is has an SMS message pending for receipt, it launches the SM Receive application. This application retrieves the SMS message(s). If the message is a standard SMS message, it routes the message to the application's "Received messages" folder.
If the message is targeted to a specific application, the SM Receive application contacts the mailbox and places the message in the mailbox's inbox . The mailbox then contacts the application by sending it a message ( MSG_META_MAILBOX_NOTIFY_MESSAGE_AVAILABLE ). If the mailbox cannot contact the application, it re-routes the message back to the SM Receive application.
You do not need to know how the SM Receive application works, but it is useful to know the process which occurs when an SMS message is received.
When the inbox receives a message that it determines is destined for a specific application, the mailbox will contact that application's process class with MSG_META_MAILBOX_NOTIFY_MESSAGE_AVAILABLE . This message passes a token identifer of the SMS message.
If you wish your application to handle an SMS message, you will need to write a message handler for MSG_META_MAILBOX_NOTIFY_MESSAGE_AVAILABLE . It should perform the following steps:
MailboxAcknowledgeReceipt()
to inform the mailbox that we're handling the message. Pass the token identifer of the SMS message that was passed with
MSG_META_MAILBOX_NOTIFY_MESSAGE_AVAILABLE
. (See Acknowledging Receipt of the Message
.)
MailboxGetBodyRef()
. (See Retrieving the Text from the VM Block
.)
MailboxDoneWithBody()
to instruct the mailbox to release the VM reference to the text. (See Cleaning Up
.)
Mailbox DeleteMessage()
, passing the token referring to this message. These specific steps are described in more detail below:
MailboxAcknowledgeMessageReceipt()
When your application receives an SMS message with
MSG_META_MAILBOX_NOTIFY_MESSAGE_AVAILABLE
, your first order of business should be informing the mailbox that you have the message. To do this, send the mailbox
MailboxAcknowledgeMessageReceipt()
, passing it the message token.
Code Display 3-6 Acknowledging Receipt of an SMS Message
/* * Each application which wishes to receive SMS messages should create a * MSG_META_MAILBOX_NOTIFY_MESSAGE_AVAILABLE handler in the app's main prcoess * class. */
@method MyProcessClass, MSG_META_MAILBOX_NOTIFY_MESSAGE_AVAILABLE {
/*
* First we inform the mailbox that we've received the message. We pass the
* `msg' token that was passed to this message in the first place.
*/
MailboxAcknowledgeMessageReceipt(msg);
/* To be continued ... */
MailboxGetBodyRef()
As we indicated in Storing the Text Within a VM File
, it is convenient for the SMS message itself to be wrapped in a small
VMChain
structure. In the following section, we assume that is indeed what was done on the sending end.
Use
MailboxGetBodyRef()
to retrieve this reference to the actual text. Pass the message token, a pointer to a buffer to store the body reference, and the length of that buffer.
Code Display 3-7 Retrieving the Text
MailboxError errorCode;
VMAppTreeRef vmRef;
word refSize;
MemHandle handleToText;
TCHAR smsText[FOAM_MAX_SMS_TEXT_SIZE+1];
char *ptrToText;
/*
* First, retrieve the reference to the body of the SMS text from the mailbox
* library. Place that reference into our vmRef variable.
*/
refSize = sizeof(VMTreeAppRef);
errorCode = MailboxGetBodyRef(msg, &vmRef, &refSize);
if (errorCode == ME_SUCCESS) {
/* * Lock the block and retrieve a pointer to the SMS text. */ ptrToText = (char *) VMLock(vmRef.VMTAR_vmFile, VMCHAIN_GET_VM_BLOCK(vmRef.VMTAR_vmChain), &handleToText);
/* * Advance the pointer beyond the carriage return to get beyond the * prefix. */
while ( *ptrToText != `\r') ptrToText++;
/* Advance over the `\r' ...*/ ptrToText++;
strcpy(smsText, ptrToText);
VMUnlock(handleToText);
/* To be continued ... */
MailboxDoneWithBody(), MailboxDeleteMessage()
Finally, we need to notify the mailbox that it can delete both the text of the message (and the reference to that text) and the message itself. To perform each of these steps, call
MailboxDoneWithBody()
and
MailboxDeleteMessage()
.
Code Display 3-8 Cleaning Up the Mailbox
/* Now remove the external text and the reference to that text. */
MailboxDoneWithBody(msg, &vmRef, refSize)
/* * Finally, delete the "message" including the message token and any * information included with it. */
MailboxDeleteMessage(msg);
}
}