| C H A P T E R 2 |
|
Porting the WMA Optional Packages |
This chapter discusses the design and porting of the Java Wireless Client software's wireless messaging subsystem. The wireless messaging subsystem implements the messaging APIs defined in the Wireless Messaging APIs (WMA) JSR 120 and JSR 205. See http://www.jcp.org/en/jsr/detail?id=120 and http://www.jcp.org/en/jsr/detail?id=205 for more information.
This chapter describes porting both the JSR 120 functionality and the additional functionality provided by JSR 205. Depending on the bundles of Java Wireless Client software you have available, you might or might not have the JSR 205 functionality available.
WMA specifies an API that provides a general messaging framework and a general mechanism for establishing a messaging application. The Wireless Messaging API specification also provides more explicit information about using the API to support the Global System for Mobile Communications (GSM) Short Message Service (SMS), Code Division Multiple Access (CDMA) SMS, GSM Cell Broadcast Service (CBS), and Multimedia Message Service (MMS) protocols.
WMA is based on the CLDC Generic Connection Framework (GCF) and is built on top of Java Wireless Client software's networking subsystem. The subsystem's design provides the notion of opening a connection based on a string address, and opening a connection in either client or server mode. The wireless messaging subsystem interacts with the networking subsystem, permission management subsystem, and the push subsystem. To support the messaging API, these subsystems must be extended in the ways described later in this chapter.
The wireless messaging service has the following features:
The WMA subsystem has the following three components or layers.
The implementation layer also drills into the low-level native layer to access the platform's native API.
The following examples, among others, of the implementation layer are included with the Java Wireless Client software:
The Java Wireless Client software implementation of this porting API uses datagrams to send and receive WMA messages. Although this is acceptable given Java Wireless Client software's target platform (which has no native WMA support), it is not the right solution for all platforms. Most platforms that support WMA have a full-featured set of native SMS, CBS, and MMS APIs and use this native support to implement the porting API.
The Message Transport porting APIs are defined in the following header files:
The Message Pool APIs are defined in the following header files:
An implementation of the pool APIs, which cache messages in memory, is provided and can be used on any platform. You can find this implementation in jsr120/src/core/common/native/ram_pool.
If your implementation requires persistent storage, then you must re-implement these pool APIs.
Before porting issues are discussed, clarification of the following functional areas is warranted:
These relationships are discussed in the following sections.
Push notifications can be a part of the core VM task or a part of an external application. Typically, when an external application monitors network connections, a native interface is used to invoke the Java platform AMS implementation. When the Java platform AMS is used, monitoring for network connections is internal to the same task, allowing for easier sharing of cached inbound messages and for rapid push dispatching.
The platform software presumes that all external networking operations have taken place, including all handshakes with the SMS and MMS service center. The platform software is responsible for segmentation and reassembly (SAR) of messages. When the network is not reachable, full messages are saved persistently in an inbox or queued for delivery in an outbox.
Normally, a pool of messages is cached in memory from the system's persistent storage. When the VM is terminated abnormally, messages in the cache might be discarded and fresh messages retrieved from persistent storage the next time the VM is started.
Under normal usage, messages are delivered from the RAM cache (message pool) to the waiting application. When the message has been dispatched, the buffered message is removed from the pool and a corresponding deletion from persistent storage removes the message from the inbox. A corresponding transaction removes the message from the service center queues.
In the emulated implementation using the datagram transport, no persistent storage is used for message storage. The memory-based message pool serves as both the persistent storage and the cached message pool. Operations are synchronous and only whole messages are exchanged. Message delivery of sent messages is not delayed and no extra handshakes exist for service center protocols. This code is meant only as an emulation for testing purposes. It is below the expected porting layer, and is not intended as code to be ported to WMA networks.
Because sending and receiving WMA messages can be time consuming, these operations are asynchronous.
When the MessageConnection object's receive method is invoked, it checks the message pool for cached messages. If a message is already in the pool, it is retrieved and the message is returned to the application MIDlet. If no messages are in the pool, then the calling Java platform thread blocks, waiting for a message to appear in the pool.
At the same time, the low-level native transport code listens for WMA messages. When a message arrives, it is read, assuming it is a packed formatted byte array.
The format of this byte array is specified in jsr120_sms_protocol.h, jsr120_cbs_protocol.h, and jsr205_mms_protocol.h in the documentation for the jsr120_send_sms, jsr120_notify_incoming_cbs, and jsr205_send_mms methods, respectively. After it is read, depending on the type of message, either the SmsMessage, CbsMessage, or MmsMessage, data structure is populated and added to the message pool.
See jsr120/src/core/common/native/share/inc/jsr120_sms_structs.h, jsr120_cbs_structs.h, and jsr205/src/core/common/native/share/inc/jsr205_mms_structs.h for definitions of SmsMessage, CbsMessage, and MmsMessage. Once the message is added to the pool, an arrival notifier method is called, which unblocks the previously blocked Java platform thread. Once unblocked, the message in the pool is retrieved, returned to the application MIDlet, and deleted from the pool.
When sending a message, the Java platform layer drills into the native transport layer and calls the appropriate send method (jsr120_send_sms, jsr120_send_cbs, or jsr205_send_mms) and blocks. The low-level transport code delivers the message to the network and then invokes a callback function that unblocks the Java platform thread. Note that the Java platform thread is unblocked when the message is delivered to the network, not when it is received by the callee.
Calls to platform-dependent low-level transport code are made from methods such as Java_com_sun_midp_io_j2me_sms_Protocol_send0() and Java_com_sun_midp_io_j2me_sms_Protocol_receive0() that are contained in jsr120/src/protocol/sms/native/share/smsProtocol.c.
Similar methods exist for CBS and MMS.
The platform-dependent methods are expected to return one of the following status types:
Networking methods that deliver or receive messages synchronously return either WMA_OK or WMA_ERR as is currently implemented on the Linux, QTE, x86 platform. On some platforms that use "master mode," the networking methods return quickly and might return WMA_NET_WOULDBLOCK. In this case, the calling Java platform thread must be blocked and awakened once the operation is completed.
When porting to a new platform, the Message Transport APIs must be ported using the platform's native SMS, CBS, and MMS support. For the Message Pool APIs, Java Wireless Client software's RAM implementation works on all platforms. If an implementation based on persistent storage or native message storage support is desired, then these APIs must also be ported.
For a detailed description of porting API data types and functions see the Native API Reference. From the top page, choose Modules, then JSR205 Wireless Message API (WMA) 2.0. The API documentation for both JSR 120 (SMS and CBS) and JSR 205 (MMS) is located there.
The Message Porting APIs include methods for the following functions:
In the case of SMS, a port number can be registered, after which the platform continues to listen for incoming SMS messages that match the registered port number. For CBS a message ID can be registered, after which only those messages that match the message ID are received and stored in the pool. Similarly, for MMS, an application ID can be registered.
The following methods can be used:
Java Wireless Client software provides a generic implementation for registering IDs using simple C data structures and lists. For an example, see the following file:
jsr120/src/core/common/native/share/jsr120_sms_listeners.c
This implementation works on all platforms. If platform support is available for distinguishing messages based on port numbers or message and application IDs, it can be used to implement these methods.
Two methods are available, one for sending the message and the other a callback function that is called once the message has been delivered to the network. To avoid blocking the VM for a long time, messages are sent asynchronously. The send methods transfer the header information and message buffer to the native platform, and return quickly. The native platform is responsible for handling the entire communication session and uses an asynchronous message or the previously mentioned callback function to notify the implementation layer of the result. The following methods can be used:
Note that if the message is too long, the native platform is responsible for segmenting and sending the message.
This involves one method for SMS and CBS and three methods for MMS. All three protocols have a callback function that is called, once a message is ready for retrieval. After a WMA application registers a specified message identifier, be it a port number, message or application ID, it will continue to listen for incoming SMS, CBS, and MMS messages whose identifier matches the registered identifier. Once a message has been added to the pool, the platform software should call this callback function with the stored message. The following methods can be used:
In addition, the MMS protocol requires you to port the following two additional functions:
When an incoming MMS message arrives in the MMS proxy, the proxy calls the MMSNotification() function to send a notification to the MMS client (target device). The notification includes only the MMS header. The MMS client decides if it must fetch the message body of this MMS from the network. If the target device finds that the incoming MMS notification is for MIDP WMA, it invokes the callback function jsr205_fetch_mms(), which provides a confirmation to the native platform to go ahead and fetch the message body.
The jsr120_number_of_sms_segments, jsr120_number_of_cbs_segments, and jsr205_number_of_mms_segments methods calculate the number of protocol segments needed for sending a message. They do not send the message.
The Message Pool APIs include methods for the following functions:
A message in the pool is always associated with an identifier, be it a port number, message, or application ID. Invoke the following methods once a message is successfully added to the pool:
These notifiers unblock any blocked Java platform threads.
Once the message is retrieved, delete it from the pool.
Return a message with an identifier that matches a specified identifier, but do not delete it from the pool.
The included RAM implementation does not provide persistent storage of messages. If you need a persistent implementation, use the APIs in pcsl_file.h and pcsl_directory.h.
The WMA Push Registry subsystem manages the registration and unregistration of connections used with pushed transactions. The same code that registers a port number, message, or application ID for an application MIDlet also registers and unregisters message identifiers for the Push subsystem. See the API documentation for the following files:
The registration returns a unique identifier. At startup, the registered connections are opened and the system listens for inbound requests.
When a connection request is detected, the inbound WMA message is read. The Push subsystem is searched for a filter and if one is found, the sender's phone number for SMS or the value of the replyToAppID variable is checked against the filter. If the filter check passes, the message is added to the pool.
When the MIDlet is launched, it performs the normal input and output operations to receive inbound messages. The listConnections method in the PushRegistryImpl class returns the registered connection string. This URI can be used with the Connector.open() method to open the connection. The first message retrieved comes from the cached message that caused the push launch to be triggered.
Native code extends the existing push implementation for WMA. This code resides in the file jsr120/src/core/common/native/share/wmaPushRegistry.c.
The push code in MIDP branches appropriately into the WMA-specific handling code. An example of this push code can be found in the file midp/src/push/push_server/reference/native/push_server.c.
The WMA push shared code shipped with Java Wireless Client software contains the following features.
The push entry data structure in push_server.c includes WMA-specific information, such as appID.
pushDeleteEntry - Closes the WMA push entry
pushfindfd - Returns the WMA entry
pushcheckout - Dispatches open WMA connections
To port the WMA subsystem, the only required action is to modify the code that monitors inbound connections and reads incoming messages so that it checks the push filter and updates the push entry data structure if necessary. For an example, see jsr120/src/core/common/native/linux_qte/wmaSocket.cpp.
Calls are made to pushsetcachedflag() and pushgetfilter() after a message is received.
To support the wireless messaging subsystem, MIDlets must have permission to perform the following tasks:
TABLE 2-1 indicates the permissions that the Wireless Messaging API Specification defines and that the permission management subsystem must manage.
Copyright © 2007, Sun Microsystems, Inc. All rights reserved. SUN PROPRIETARY/CONFIDENTIAL.