This document is a single-page version of a a multi-page document, suitable for easy printing.

SMS Guide

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 Overview
  2 Using the Mailbox Library
    2.1 Mailbox Overview
  3 Sending an SMS Message
    3.1 Sending and the Mailbox Library
    3.2 Using the SMS Mailbox API
  4 Receiving an SMS Message
    4.1 SM Receive and the Mailbox Library
    4.2 Receiving an SMS Message


SMS Guide: 1 SMS Overview

The 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.


SMS Guide: 2 Using the Mailbox Library

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.


SMS Guide: 2.1 Using the Mailbox Library: Mailbox Overview

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.


SMS Guide: 3 Sending an SMS Message

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:

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.


SMS Guide: 3.1 Sending an SMS Message: 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.


SMS Guide: 3.2 Sending an SMS Message: Using the SMS Mailbox API

mailbox.goh

To send an SMS message to the outside world, an application will need to perform the following steps:

  1. Set up the text message. In many cases, the text will reside in a simple text buffer. If you wish to address the SMS message to a particular application, you will need to prepend a twelve-character prefix to the text message. The message itself will then be, at most, 148 characters in length. Without a prefix, you may send a 160-character SMS message. (See Setting Up the Text Message .)
  2. Copy the text into a VM file. The Mailbox library may store an SMS text message in a variety of formats (indicated by type 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 .)
  3. Set up the 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 .)
  4. Set up the MailboxRegisterMessageArgs structure. (See Setting Up the MailboxRegisterMessageArgs .)
  5. Call MailboxRegisterMessage() . (See Registering the Message .)
  6. Upon success, notify the Mailbox library that we are done with the VM file.

These steps are detailed in the sections following.

Setting Up the Text Message

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 );
}

Storing the Text Within a VM File

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 .
VMTAR_ 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:

  1. Call 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.

    This routine returns a VMFileHandle.
  2. Allocate a VM block within this file, using VMAlloc().
  3. Lock the block down using 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.
  4. Copy the text from your text buffer into the locked block starting at its segment address. (You will need to skip two bytes for the VMChainLink that begins the block.)
  5. Dirty the block using VMDirty().
  6. Unlock the block using VMUnlock().
  7. Store the VM file and VM block within a 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;

Setting Up the SMSending Options

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:

  1. Call MailboxGetAdminFile() to retrieve the VMFileHandle of the Mailbox administration file. This is where you will copy your SMS parameters.
  2. Allocate an ungrouped DB item within this file, using DBAllocUngrouped().
  3. Lock the DB item using DBLockUngrouped().
  4. Copy your basic SMSendingOptions parameters into this DB item.
  5. Read the service center number from the .INI file using InitFileReadStringBuffer(). Copy that number into the DB item.
  6. Dirty the block using DBDirty().
  7. Unlock the block using DBUnlock().
The SMSendingOptions structure

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
SMSO_ replyPath contains an SMReplyPath value which indicates whether the recipient may reply to the message through the sender's service provider. Possible values are:
SMRP_NO
This flag is set by default and indicates that the recipient must reply through the recipient's service provider.
SMRP_YES
Setting this flag allows the recipient to reply through the sender's service provider.
SMSO _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:
SMVP_1_HOUR
SMVP_6_HOURS
SMVP_24_HOURS
SMVP_1_WEEK
SMVP_MAX (The actual value of SMVP_MAX will vary by service provider.)
SMSO_ 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:
SMMC_NORMAL
Deliver the message as a normal SMS message. This is the default value.
SMMC_FAX_GROUP_3
Deliver the message as a fax according to the fax group 3 standard.
SMMC_FAX_GROUP_4
Deliver the message as a fax according to the fax group 4 standard.
SMMC_VOICE
Deliver the message as a voice mail message.
SMMC_ERMES
Deliver the message according to the European Radio Messaging System standard.
SMMC_PAGING
Deliver the message as an alpha-numeric page.
SMMC_EMAIL
Deliver the message as an Internet e-mail message.
SMMC_X400
Deliver the mesage according to the X400 e-mail standard.
SMSO_ 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.
Reading a String From the .INI File
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);

Setting Up the MailboxRegisterMessageArgs

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.)

  1. Indicate the format in which you wish the SMS message stored while it resides in the outbox. (The mailbox will call the appropriate mailbox data driver when the message is registered.)
  2. Indicate the format of the actual message. This is where you tell the mailbox that this message is an SMS message.
  3. Indicate the VM file in which the SMS message is stored.
  4. Tell the mailbox to use the SMS transport driver when the mailbox sends the message.
  5. Give the mailbox the address of the recipient.
  6. Indicate the DB item where the SMSendingOptions are located.
  7. Tell the mailbox when to begin delivery of the message and when to give up delivery attempts if unsuccessful.

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;
Data Format for Storage

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.

MRA_ 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
...stores a word of data indicating the type of data driver that will be used to store the message. For SMS messages, we will use a Geoworks data driver referenced by a GeoworksMailboxStorageID. The following types are valid:
	GMSID_FILE
	GMSID_VM_TREE
As we indicated earlier, SMS messages should be stored in VM trees. You do have the option of storing them as GEOS files as well, but VM trees are easier to manipulate.
MS_manuf
...stores the ManufacturerID of the data driver being used. Since we will be using Geoworks VM trees, we will store MANUFACTURER_ID_GEOWORKS in this location.
Data Format of the Message
MRA_bodyFormat
...indicates the format of the actual data being stored (in its original source). This field takes an argument of type MailboxDataFormat . This is defined below:
typedef struct {
	word			MDF_id;
	ManufacturerID			MDF_manuf;
} MailboxDataFormat;
MDF_id
...stores a word of data indicating the data stored in the message. We will use a Geoworks data format referenced by a GeoworksMailboxDataFormatID. Pass GMDFID_SHORT_MESSAGE in this field to indicate that the message is a Geoworks SMS message.
MDF_manuf
...stores the ManufacturerID of the format. Since we will be using Geoworks SMS , we will store MANUFACTURER_ID_GEOWORKS in this location.
References to the VM Tree Structure
MRA _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 .
MRA_ bodyRefLen stores the length of the reference indicated in MRA_ bodyRef . In this case, we will store the size of the VMAppTreeRef structure.
The Transport Driver
The Mailbox uses an applicable transport driver when it wants to deliver a message to the outside world. You specify this transport driver in the MRA_ transport field.
MRA _transport takes an argument of type MailboxTransport . This is defined below:
typedef struct {
	word			MT_id;
	ManufacturerID			MT_manuf;
} MailboxTransport;
MT_id
...stores a word of data indicating the type of transport driver that will be used to deliver the message. For SMS messages, we will use a Geoworks transport driver referenced by a GeoworksMailboxTransportID.
To send an SMS message, we will use the SM transport driver referenced by GMTID_SM.
MT_manuf
...stores the 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
...stores an unsigned value that the the transport driver uses. For SMS, set this to zero.
MRA_transAddrs
stores the address of the eventual recipient. This address is stored as a pointer to a MailboxTransAddr structure; it is only important that the transport driver understand the format for this address.

If there are multiple recipients, this pointer references multiple MailboxTransAddr structures. This structure is defined below:
typedef struct {
	const void			*MTA_transAddr;
	unsigned			MTA_transAddrLen;
	const char			*MTA_userTransAddr;
} MailboxTransAddr;
MTA_transAddr
...stores a pointer to the recipient address, understood by the transport driver. (For SMS this is a simple ASCII text string of the recipient's phone number.)
MTA_transAddrLen
...stores the length of the address stored in MTA_transAddr.
MTA_userTransAddr
...stores a user-readable version of the address, as a null-terminated text string. Because the SMS address is already stored as an ASCII text value, this field will be the same as MTA_transAddr.
MRA_numTransAddrs
...stores the number of recipient addresses stored in MRA_transAddrs.
MRA_transData
...stores data understood by the transport driver. As mentioned in Setting Up the SMSending Options , the SMS transport driver expects a DBItem containing a structure of type SMSendingOptions .
MRA_flags
...stores a field of MailboxMessageFlags.
For SMS messages, the only flag you may care about is MMF_DELETE_BODY_AFTER_TRANSMISSION, which will delete the VM file containing the SMS message after it is delivered. Do not set any other flags.
MRA_summary
stores a text string that the Outbox displays to indicate the type of message being delivered. For example, if you are sending a chess move for a game in progress, you might set this field to display "Chess Move."
MRA_destApp
...stores the GeodeToken of the destination application.
MRA_startBound
...indicates a time and date (of type FileDateAndTime ) to begin transmission of the message. You may also pass the value MAILBOX_NOW (0) for immediate delivery.
MRA_endBound
...indicates a time and date (of type 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;

Registering the Message

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(&registerArgs, &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

SMS Guide: 4 Receiving an SMS Message

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.


SMS Guide: 4.1 Receiving an SMS 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.


SMS Guide: 4.2 Receiving an SMS Message: Receiving an SMS Message

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:

  1. Call 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 .)
  2. Retrieve the VM reference to the message with MailboxGetBodyRef() . (See Retrieving the Text from the VM Block .)
  3. Lock down the VM block and retrieve a pointer to the text.
  4. Copy the text to a local buffer.
  5. Unlock the VM block.
  6. Call MailboxDoneWithBody() to instruct the mailbox to release the VM reference to the text. (See Cleaning Up .)
  7. Call Mailbox DeleteMessage() , passing the token referring to this message.

These specific steps are described in more detail below:

Acknowledging Receipt of the Message

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 ... */

Retrieving the Text from the VM Block

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 ... */

Cleaning Up

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);
    }
}

This document is a single-page version of a a multi-page document, suitable for easy printing.