WAP Push SMS messages are widely used for pushing polyphonic ringtones and wallpaper images to mobile phones. However, as you will see, they also present a compelling method of directing people to WAP sites without visibility on the operator's WAP Portals.
This article presents a set of C# classes that generate an SMS message that instructs a mobile to browse to a given URL.
Instructing The Device
WAP Push messages can contain a number of different bodies all designed to accomplish slightly different outcomes. The one we are interested in is the Service Indication. This is an XML document (DTD here) that contains a URL for the handset to browse to. For example:
<indication href="http://wap.yahoo.com/" action="signal-high">
A WAP Push to the Yahoo site
In the mobile world, bandwidth and reliable connections are at a premium, so the method for getting this message to a device needs to be reliable and compact. XML has many strengths, compactness however is not one of them. Step in SMS and WBXML.
SMS is a reliable (depending on the service provider) store and forward mechanism for sending messages to mobile devices. Its use is not limited to person to person communication. It drives voice mail alerts, phone configurations, MMS notifications, and a whole host of other features we expect from mobile networks. The problem is that it is restricted to 140 bytes of data.
WBXML is binary format of XML that allows for compact transmission, while still preserving the structure and content of XML documents. Devices have inbuilt knowledge of certain XML DTDs that they are able to parse and understand.
One way this compactness is achieved is by a Tag Code Space being reserved for each DTD. Instead of the full tag name being sent, just a byte value is used to indicate the presence and position of the Tag. The Tag Code Space for the Service Indication DTD is shown below:
Another method is to replace common attributes and known values with byte values. In the case of the action attribute of the indication tag, which gives an indication of what level of interruption the device should attempt on receipt of this message, these are:
Use of these methods allow the XML document to be compressed sufficiently for transmission by SMS to the target device. A full description of the Service Indication can be found at the WAP Forum section of the Open Mobile Alliance web site.
Pushing The Instruction
Now that the instruction in the form of a Service Indication has been encoded, the data needs to be packaged into an SMS message. This requires two additional protocol layers to be wrapped around the instruction in order that it is read correctly by the recipient device.
The first layer is the WSP (Wireless Session Protocol). This is analogous to HTTP in the wired world, where a series of headers describe the content that is contained. As with the WBXML encoded Service Indication, these are actually transported as well known byte values in order to preserve bandwidth. The headers used in the WAP Push message are:
Finally, the WDP (Wireless Datagram Protocol). For those of you who are familiar with sending Smart Messages to Nokia phones like VCard, Ringtones, Operator Logos, etc., this is the UDH (User Data Header). This contains an information element that describes the destination port on the mobile phone. This is used by the phone to decide which application it should fire up on receipt of this message. In our case, the WAP Browser.
Once all the layers are in place, you now have a series of bytes that have to be submitted to the mobile phone.
Using the code
The core classes comprise a
ServiceIndication which is responsible for creating the content of the push; and
PushMessage which is responsible for generating the complete message by wrapping the additional protocol layers. The classes
WDP are holders for constants and statistics relating to the different protocol layers. The following code demonstrates how the body is generated:
string href = "http://wap.yahoo.com";
string text = "A WAP Push to the Yahoo site";
PushMessage message = new PushMessage(href, text);
HexDecoder decoder = new HexDecoder();
string body = new string(decoder.GetChars(message.GetSMSBytes()));
I have included a
HexDecoder class we use internally for converting a byte array into Hex string.
Once the message body has been created, it's a simple process to send the message using a mobile phone connected to the PC's serial port, or an SMS Web Service such as this.
Points of Interest
The great thing about sending these kinds of messages to mobile phones is that they ignore them if they don't understand them. It makes debugging a nightmare.
I started with the Service Indication specification on the OMA web site but discovered that the handsets out there are not as up-to-date. In order to get this to work, I had to drop the creation and expiry attributes as well as drop the version number to 1.1.
ServiceIndication class encodes itself to WBXML in a fairly procedural way. Tempted as I was to write a generic WBXML encoder, XP teaches us that simple is good ;).
The content length byte value in the WSP header has the high byte set, which suggests that the content is restricted to 128 bytes. This makes sense given the 140 bytes available, if anyone can clarify the position on this, I would appreciate it.