Short Message Services 
by Ron Hume


Listing One
Err Connection::ConnectToSMPPServer ( Server *server, Config *config )
{
    Err rc = SUCCESS;
    /* BindTransmitter inherits from PDU Base class which contains 
                                                         header members */
    BindTransmitter *bind_transmitter = new BindTransmitter();

    /* Open the transmitter connection */
    TCPIP_Connection TCPIPConnection = new TCPIP_Connection;
    rc = TCPIPConnection->Connect ( server->hostname, server->port );
    if ( rc != SUCCESS )
    {
        ( void ) ProcessRC ( rc );
        delete TCPIPConnection;
        delete bind_transmitter;
        return ( rc );
    }
    setState ( CONNECTED );

    /* fill in BIND_TRANSMITTER PDU and send */
    ( void ) bind_transmitter->setSystemId ( config->getSystemId() );
    ( void ) bind_transmitter->setPassword ( config->getPassword() );
    ( void ) bind_transmitter->setSystemType ( config->getSystemType() );
    ( void ) bind_transmitter->setAddressRange ( config->getAddressRange() );
    ( void ) bind_transmitter->setAddressType ( ( unsigned char ) NULL );
    ( void ) bind_transmitter->setAddressNPI ( ( unsigned char ) NULL );
    ( void ) bind_transmitter->setInterfaceVersion ( ( unsigned char ) 0x34 );
    
    /* fill in the header */
    /* reset sequence number */
    setSequenceNumber ( 1 );
    ( void ) bind_transmitter->setSequenceNumber ( nextSequenceNumber() );

    /* Pack the PDU into buffer */
    ( void ) bind_transmitter->Pack ( );
    if ( ( rc = TCPIPConnection->Send ( bind_transmitter->Payload(), 
                           bind_transmitter->PayloadSize() ) ) != SUCCESS )
    {
        ( void ) ProcessRC ( rc );
        ( void ) TCPIPConnection->Disconnect();
        setState ( IDLE );
        delete TCPIPConnection;
        delete bind_transmitter;
        return ( rc );
    }
    /* put on outstanding transactions list - waiting for response */
    SMPPList.add ( bind_transmitter, config->getResponseTimer(), 
                                                   ConnectToSMPPCallback );
    return ( ( Err ) SUCCESS );
}


Listing Two
Err Connection::DoMailCheck ( UserProfile *user, Config *config )
{
    Err rc;
    unsigned int num_msg;

    /* check if user has mail */
    if ( ( rc = CheckForNewMail ( user, &num_msg ) ) != SUCCESS )
    {
        /* some error occurred */
        ( void ) ProcessRC ( rc );
        return ( rc );
    }
    /* how many messages are there ? */
    if ( num_msg > 0 )
    {
        rc = DoNotify ( user, config, num_msg );
        return ( rc );
    }
    /* none? ok - return */
    else /* num_msg == 0 */
    {
        rc = ( Err ) NO_MAIL;
        return ( rc );
    }
    /*NOTREACHED*/
    return ( ( Err ) SUCCESS );
}
Err Connection::DoNotify ( UserProfile *user, Config *config, 
                                                   unsigned int number )
{
    
    /* DataSM inherits from PDU which contains the header member accessors */
    DataSM *msg = new DataSM();

    /* fill in DATA_SM PDU and send */
    /* set teleservice identifier */
    ( void ) msg->setServiceType ( config->getServiceType() );
    
    /* set source address properties */
    ( void ) msg->setSourceAddressType ( config->getAddressType() );
    ( void ) msg->setSourceAddressNPI ( config->getAddressNPI() );
    ( void ) msg->setSourceAddress ( config->getSourceAddress() );
    
    /* set destination address properties */
    ( void ) msg->setDestAddressType ( user->getAddressType() );
    ( void ) msg->setDestAddressNPI ( user->getAddressNPI() );
    ( void ) msg->setDestAddress ( user->getAddress() );

    /* turn on any special attributes                                      */
    /* ( we set transaction mode here by using the ESM_FORWARD_MODE flag ) */
    /* following causes 00000010 to be encoded, as follows:                */
    /* 00xxxxxx  No GSM Specific Features                                  */
    /* xx0000xx  Default message type                                      */
    /* xxxxxx10  Forward (transaction) mode                                */
    ( void ) msg->setESMClass ( ESM_GSM_FEAT_NONE | 
                                  ESM_DEFAULT_MSG_TYPE | ESM_FORWARD_MODE );
    /* no delivery receipt (the default) option - 0x00 */
    ( void ) msg->setRegisteredDelivery ( 0x00 );

    /* data encoding is ASCII */
    ( void ) msg->setDataCoding ( CODING_IA5 );

    /* optional parameters */

    /* how long for SMSC to hold onto msg */
    if ( user->msg_time_to_live != 0 )
    {
        ( void ) msg->setTimeToLive ( user->msg_time_to_live );
    }
    /* indicate how many new emails are waiting */
    /* 99 is the max value for this parameter */
    if ( number > 99 ) number = 99;
    ( void ) msg->setNumberOfMsgs ( number );

    /* alert MS on message delivery - turn on */
    ( void ) msg->setAlertOnDelivery ( TRUE );

    /* the message... */
    ( void ) msg->setPayload ( "You have new mail" );
    
    /* fill in the header */
    ( void ) msg->setSequenceNumber ( nextSequenceNumber() );

    /* Pack the PDU into buffer */
    ( void ) msg->Pack ( );

    /* send message */
    if ( getState () == BOUND )
    {
        if ( ( rc = TCPIPConnection->Send ( msg->Payload(), 
                                      msg->PayloadSize() ) ) != SUCCESS )
        {
            ( void ) ProcessRC ( rc );
            delete msg;
            return ( rc );
        }
    }
    else
    {
        delete msg;
        return ( ( Err ) NOT_BOUND );
    }
    /* put on outstanding transactions List - waiting for response */
    SMPPList.add ( msg, config->getResponseTimer(), DataSMCallback );
    return ( ( Err ) SUCCESS );
}

Listing Three
Err Connection::DisconnectFromSMPPServer ( Config *config )
{
    Err rc; 
    /* UnBind inherits from PDU which contains the header member accessors */
    UnBind *unbind = new UnBind();

    /* fill in UNBIND PDU and send */
    /* fill in the header */

    unbind->setSequenceNumber ( nextSequenceNumber() );
    unbind->setCommandLength ( 16 );    

    /* send the message */
    if ( getState() == BOUND )
    {
        if ( ( rc = TCPIPConnection->Send ( unbind->Payload(), 
                                  unbind->PayloadSize() ) ) != SUCCESS )
        {
            ( void ) ProcessRC ( rc );
            ( void ) TCPIPConnection->Disconnect();
            setState ( UNBOUND );
            setState ( IDLE );
            delete unbind;
            delete TCPIPConnection;
            return ( rc );
        }
    }
    /* put on outstanding transactions queue - waiting for response */
    SMPPList.add ( unbind, config->getResponseTimer(), 
                                              DisconnectFromSMPPCallback );
    return ( ( Err ) SUCCESS );
}
Err Connection::DisconnnectFromSMPPCallback ( UnBind *unbind, 
                              UnBindResp *resp, unsigned short timer_flag )
{
    /* set connection state to UNBOUND */
    setState ( UNBOUND );

    if ( timer_flag == TRUE )
    {
        /* response timer expired - timeout */
        ( void ) LogError ( INFO, UNBIND_TIMEOUT );
        /* continue tearing down connection anyway... */
    }
    /* disconnect socket */
    ( void ) TCPIPConnection->Disconnect ( );

    /* free up objects */
    delete unbind;
    delete resp;        
    delete TCPIPConnection;

    /* set connection state to IDLE */
    setState ( IDLE );
    return ( ( Err ) SUCCESS );
}





4

