Updated on Oct,21, 2001

Document from BellSouth Wireless Data

I started my first IAS programming with IAS Description and Programming Guide

Notes on Cingular IAS Programming for custom host

All the neccessary programming guides are covered in the above guide of BellSouth, I think. The following is what I have really built for my application. If you find something wrong, please let me know at dt1649651@yahoo.com. All of your comments or criticism are appreciated.

RIM 950/957 devices communicate with each other using Mobitex network. Each device is assigned a unique number call MAN ( Mobitech Access Number ) as identified number. And the data units that they exchange are call MPAK ( Mobitech packet ).

In order to enable a custom host and Rim devices communicate with each other, an IAS server is introduced. IAS server acts as a gateway between the custom host and the Mobitex network. The custom host is assigned a unique MAN number, too ( and it becomes a big Rim device, with powerful compilers, tools, and a big vivid monitor [perhaps it is better on to mention this monitor in my case. It is a Linux box, and I rarely need to use this monitor or the keyboard] ). To the Rim devices, this custom host is just another Rim device. In their point of view, they communicate this host exactly as with other Rim devices. Custom communicates with IAS thru tcp protocol. There is at least another option for custom host to communicate with Mobitech network, that is X.25, but it is beyond of the scope of this note.

You also need to register all your Rim 950/957 MAN numbers to be in the same group ( CUG ) with the number assigned to the custom host. This will enable your MPAKs of the devices to be able to be forwarded to the custom host, and vice versa.

Because the data unit that Rim devices use is MPAK, these MPAK are tunnelled under tcp: each MPAK is encapsuled with a four-byte header. This header contains the 2-byte length of the MPAK. This protocol is called MDOT ( MPAK Datagram over TCPIP ). Then, the main work the custom host must do, in order to exchange MPAKs with other Rim devices, are:

  • establish the tcp connection with IAS host. ( When you register with Cingular, you need to submit the custom host ip address to them, and you will know the ip address and port of the IAS server ).
  • encapsulte MPAK with 4-byte header and send it over the tcp connection, or
  • read the 4-byte header, then read the corresponding MPAK after this header
  • 1. The structure of the MDOT header
    This structure has four bytes: one byte for version ( cureently 2 ), one byte for flags ( that must be zero for now ), anf the rest is a short int for the length of the MPAK that followed. This 2-byte length is in network-byte-order.The following is defined in my header file.

    typedef struct tagIASHeader
    {
        unsigned char version;
        unsigned char flags;    // must be zero
        unsigned short length;  
    } IASHeader;
    

    The following code is part of the receive module.

    // read the IAS header
    IASHeader iasheader;
    unsigned char *p;
        if ( ProcessTcpReceive( isocket, ( unsigned char*) &iasheader, sizeof(iasheader) ) == -1 )
            continue;
        if( iasheader.version != IAS_VERSION || iasheader.flags != 0 )
        {
            // Out-of-boundary error may happen
            ProcessErrorOrOutOfSync();
            continue;
        }
        unsigned int mpaklength = ntohs( iasheader.length );
        sprintf( message, "InIASLayerProc receives header with mpak length of %d", mpaklength );
        writelog_iniaslayer( message );
    
    ProcessTcpReceive is an encapsulation of recv with some processing codes for NONBLOCK I/O, and to detect if the connection is still good.
    Be careful that the MPAK length must be converted to host-byte-order befire using.
    ProcessErrorOrOutOfSync() is activated in the case out-of-format error. What it does here is to close the connection, wait for N seconds ( this N number is a variable ) then make the connection again. In fact, after 2 months running the custom host with a pilot test with 16 RIMs, this function has never been activated.

    2. Building a reliable protocol layer over MPAK
    I have no way to be sure that MPAKs will reach their destination sucessfully, and if they reach in the order they are sent. Therefore I build another protocol layer over MPAK. What I built can be temporaroly called "reliable connectionless session" in the meaning that each sending session needs to be acknowledged. Also, if a session is so big that it must be laid over many mpaks, then these mpaks will be numberred, and the receivingend must check the order or lost of mpaks. In cast of losing mpak, the receicing end must send a request to the sender to resend.

    This is a little similar to "reliable UDP"; why don't I build a connection-oriented protocol ? The reasons are I have not enough time ( and talent ) to do so, also there are some rumor that there will be a tcpip stack for RIM, and this specific protocol seems serving the current requirements of my application rather good.

    To do this, my protocol divides the MPAK data part into two parts : Datagram header and Subdata. The Datagram header is to help controlling the reliable feature, and the Subdata is for the data of my application.

    typedef struct tagDatagramHeader
    {
        unsigned short int sessionnumber;
        unsigned short int datagramnumber;
        unsigned short int datagramtotal;
        unsigned short int length;
        unsigned char  protocol;
    } DatagramHeader;
    
  • sessionnumber is an ascending number. The acknowledge MPAK must include this session number so that the sender knows which session has been recevied.
  • datagramnumber specified the order of this mpak in the whole message. It will help detecing lost or out of order MPAKs.
  • datagramtotal is the total number of MPAKs for this message.
  • length specified the length of the of the data part. This is necessary for the last MPAK of a given message. All MPAKs that are not the last MPAK of a given message always has the Subdata part to be full.
  • Protocol: determine what kind of protocol that the Subdata has. Currently it supports one value for my company-specific application, and one value for email.

    The common format for my MDOT is as follows:

    [Start of MDOT]
        [MDOT Header]
        unsigned char version;
        unsigned char flags;    
        unsigned short length;
        [Start of MPAK]   
            [Start of MPAK Header]   
              See Radio Guide.
            [End of MPAK Header]   
            [Start of MPAK Data]   
                [Start of Datagram Header]
                unsigned short int sessionnumber;
                unsigned short int datagramnumber;
                unsigned short int datagramtotal;
                unsigned short int length;
                unsigned char  protocol;
                [End of Datagram Header]
            [Subdata]
              My protocol-specific header ( if available) and real data here.
            [End of MPAK Data]   
        [End of MPAK]   
    [End of MDOT]
    
    We can see that with the Datagram Header inserted into the MPAK data, I loose at least 9 bytes for the DatagramHeader. To be able to make the data smaller, I use the porting version of zlib to compress that MPAK data. The compression library is really a good thing to do. After adding the compression layer, the above structure becomes:
    [Start of MDOT]
        [MDOT Header]
        unsigned char version;
        unsigned char flags;    
        unsigned short length;
        [Start of MPAK]   
            [Start of MPAK Header]   
              See Radio Guide.
            [End of MPAK Header]   
            [Start of MPAK Data]   
                unsigned short decompression_length;
                unsigned char  compression_data[];
            [End of MPAK Data]   
        [End of MPAK]   
    [End of MDOT]
    
    My custom host 's application uses pthread to deal with this multiple layers:
  • Two threads at session layer: processing incoming and outgoing sessions, interpreting incoming sessions to application commands to execute
  • Two threads at datagram layers: check the order of the incoming datagram, check if some datagram needs to be resent, order the datagram in the order they are sent, check to see if all datagrams are enough for a complete session, cut outgoing sessions into datagrams, ...
  • Two threads at MPAK layer : strip and check the MDOT header of the incoming MDOT packets, encapsulate the outgoing MPAKs with the MDOT header, and put them into the outgoing MDOT queue.
  • One thread for tcp connection: this one will take care of the connection with the IAS server, detecting lost connection, reestablish connection, get the MDOTs from the outgoing queue to send out, receiving incoming MDOTs and submit to MPAK layer pthread
  • Other threads for executing commands and interfacing with administrators thru telnet sessions.
  • More information on pthread propgramming

    3. Keep your custom host connect with IAS server up
    One of the guides that IAS Description and Programming Guide states is to try to reconnect after a disconnect. The reason is to be able to receive MPAKs from Rim devices send to the server.

    Tcpip 's recv is a good way to detect if the connection is closed. If recv returns 0, it means the other end has been closed. If the socket on which recv is wating for is on NON-BLOCK mode, then if recv returns -1 and variable errno is not EWOULDBLOCK, then it indicates there is an error. To detect these cases, custom host put the socket in non-blocking mode, then poll for data every M miliseconds.

    Also tcpip 's send can be used to detect also. If you call a send when the connection is closed, send will return -1 with errno having signal error EINTR. This is a PIPE BROKEN error. This means that if your application does not catch this signal, it will be core-dumped.

    4. Prepare to process error MPAKs
    If some MPAK can not reach the RIM devices for some reason, it will be sent back to your custom host with the status 's traffic bits set to error. For receiving MPAKs, these bits are bit 5 to 7 of the status byte. Only 000xxxxx and 001xxxxx of these three bits are acceptable as no error generated. All other values mean error. The most common error I met is 011xxxxx. It means No Transfer : the packet could not be delivered to the destination device.

    The custom host can not just simply resend the error MPAKs, because it may be the case that the device has been turned off or it may be because of the problem from Cingular towers. If you keep resending, the IAS server will keep sending back to the custom host. The custom host needs to implement some mechanic to solve this problem. For example, an error counter that reaches its maximum number will signal the application to stop resending and set a flag indicating that the corresponding device is out-of-service at this time. Any MPAK from the out-of-service device will signal the custom host to put this device back to normal state.

    5. My server configuration
    - P3-800 Mhz, 256 Mb RAM
    - Adaptec 29160 with a 20Gb UltraWide SCSII drive
    - Linux Redhat 7.1
    - gcc 3.0: Its configure parameter is
    Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.0/specs
    Configured with: ../gcc-3.0/configure --enable-threads=posix
    Thread model: posix
    gcc version 3.0
    - Interbase 6.0
    - Apache server with PHP 4.0

    I use the gcc 3.00 in order to be able to use STL lirbary. With all the lists, vectors of datagrams and mpaks ... it would take me a lot of time if I didn't use STL. I am very happy that I have spent time on STL, then I gain a lot of time later.

    Counter