Blog Movement

This blog has been moved to this address: http://thefundoowriter.wordpress.com/

Please visit: http://thefundoowriter.wordpress.com/

Sorry for your inconvenience...

An example SMS Server component

Posted by Abhinaba On 1:10 AM

Cracked code which helps you in understanding how Mobile SMS SERVER GATEWAY/CENTER works???? - An excellent code.

/*****************************************************************************
* smsc_smpp.c - Short Message Peer to Peer Provisioning Protocol 3.3
* Mikael Gueck for WapIT Ltd.
*/
 
#include "errno.h"
#include "stdarg.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/time.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
 
#include "smsc.h"
#include "smsc_smpp.h"
#include "octstr.h"
#include "wapitlib.h"
 
SMSCenter *smpp_open(char *host, int port, char *system_id, char *password, char* system_type, char *address_range) {
 
        SMSCenter *smsc = NULL;
        struct smpp_pdu *pdu = NULL;
        struct smpp_pdu_bind_receiver *bind_receiver = NULL;
        struct smpp_pdu_bind_transmitter *bind_transmitter = NULL;
 
        smsc = smscenter_construct();
        if(smsc==NULL) goto error;
 
        smsc->type = SMSC_TYPE_SMPP_IP;
        sprintf(smsc->name, "SMPP:%s:%i:%s:%s", host, port, system_id, system_type);
        smsc->latency = 100*1000;
 
        smsc->hostname = strdup(host);
        smsc->port = port;
 
        smsc->smpp_system_id = (system_id != NULL) ? strdup(system_id) : NULL;
        smsc->smpp_system_type = (system_type != NULL) ? strdup(system_type) : NULL;
        smsc->smpp_password = (password != NULL) ? strdup(password) : NULL;
        smsc->smpp_address_range = (address_range != NULL) ? strdup(address_range) : NULL;
 
        /* Create FIFO stacks */
        smsc->unsent_mt = fifo_new();
        if(smsc->unsent_mt == NULL) goto error;
 
        smsc->sent_mt = fifo_new();
        if(smsc->sent_mt == NULL) goto error;
 
        smsc->delivered_mt = fifo_new();
        if(smsc->delivered_mt == NULL) goto error;
 
        smsc->received_mo = fifo_new();
        if(smsc->received_mo == NULL) goto error;
 
        smsc->fifo_t_in = fifo_new();
        if(smsc->fifo_t_in == NULL) goto error;
 
        smsc->fifo_t_out = fifo_new();
        if(smsc->fifo_t_out == NULL) goto error;
 
        smsc->fifo_r_in = fifo_new();
        if(smsc->fifo_r_in == NULL) goto error;
 
        smsc->fifo_r_out = fifo_new();
        if(smsc->fifo_r_out == NULL) goto error;
 
        /* Create buffers */
        smsc->data_t = data_new();
        if(smsc->data_t == NULL) goto error;
        
        smsc->data_r = data_new();
        if(smsc->data_r == NULL) goto error;
 
        /* Open the transmitter connection */
        smsc->fd_t = tcpip_connect_to_server(smsc->hostname, smsc->port);
        if(smsc->fd_t == -1) goto error;
        debug(0, "smsc->fd_t == %i", smsc->fd_t);
        debug(0, "smsc->hostname == %s", smsc->hostname);
        debug(0, "smsc->port == %i", smsc->port);
        smsc->smpp_t_state = SMPP_STATE_CONNECTED;
 
        /* Open the receiver connection */
        smsc->fd_r = tcpip_connect_to_server(smsc->hostname, smsc->port);
        if(smsc->fd_r == -1) goto error;
        debug(0, "smsc->fd_r == %i", smsc->fd_t);
        debug(0, "smsc->hostname == %s", smsc->hostname);
        debug(0, "smsc->port == %i", smsc->port);
        smsc->smpp_r_state = SMPP_STATE_CONNECTED;
 
        /* Push a BIND_RECEIVER PDU on the [smsc->unsent] stack. */
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        pdu->id = SMPP_BIND_RECEIVER;
        smsc->seq_r = 1;
        pdu->sequence_no = 1;
        bind_receiver = malloc(sizeof(struct smpp_pdu_bind_receiver));
        if(bind_receiver==NULL) goto error;
        memset(bind_receiver, 0, sizeof(struct smpp_pdu_bind_receiver));
        strncpy(bind_receiver->system_id, system_id, 16);
        strncpy(bind_receiver->password, password, 9);
        strncpy(bind_receiver->system_type, system_type, 13);
        strncpy(bind_receiver->address_range, address_range, 41);
        pdu->message_body = bind_receiver;
        fifo_push(smsc->fifo_r_out, pdu);
        
        /* Push a BIND_TRANSMITTER PDU on the [smsc->unsent] stack. */
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        pdu->id = SMPP_BIND_TRANSMITTER;
        smsc->seq_t = 1;
        pdu->sequence_no = 1;
        bind_transmitter = malloc(sizeof(struct smpp_pdu_bind_transmitter));
        if(bind_transmitter==NULL) goto error;
        memset(bind_transmitter, 0, sizeof(struct smpp_pdu_bind_transmitter));
        strncpy(bind_transmitter->system_id, system_id, 16);
        strncpy(bind_transmitter->password, password, 9);
        strncpy(bind_transmitter->system_type, system_type, 13);
        strncpy(bind_transmitter->address_range, address_range, 41);
        pdu->message_body = bind_transmitter;
        fifo_push(smsc->fifo_t_out, pdu);
 
        /* Done, return */
        return smsc;
 
error:
        error(0, "smpp_open: could not open");
        pdu_free(pdu);
 
        /* Destroy FIFO stacks. */
        fifo_free(smsc->unsent_mt);
        fifo_free(smsc->sent_mt);
        fifo_free(smsc->delivered_mt);
        fifo_free(smsc->received_mo);
        fifo_free(smsc->fifo_t_in);
        fifo_free(smsc->fifo_t_out);
        fifo_free(smsc->fifo_r_in);
        fifo_free(smsc->fifo_r_out);
 
        /* Destroy buffers */
        data_free(smsc->data_t);
        data_free(smsc->data_r);
 
        smscenter_destruct(smsc);
        return NULL;
}
 
int smpp_reopen(SMSCenter *smsc) {
 
        struct smpp_pdu *pdu = NULL;
        struct smpp_pdu_bind_receiver *bind_receiver = NULL;
        struct smpp_pdu_bind_transmitter *bind_transmitter = NULL;
 
        if(smsc==NULL) goto error;
 
        /* Destroy FIFO stacks. */
        fifo_free(smsc->unsent_mt);
        fifo_free(smsc->sent_mt);
        fifo_free(smsc->delivered_mt);
        fifo_free(smsc->received_mo);
        fifo_free(smsc->fifo_t_in);
        fifo_free(smsc->fifo_t_out);
        fifo_free(smsc->fifo_r_in);
        fifo_free(smsc->fifo_r_out);
 
        /* Destroy buffers */
        data_free(smsc->data_t);
        data_free(smsc->data_r);
 
        /* Close sockets */
        close(smsc->fd_t);
        close(smsc->fd_r);
 
        /* Create FIFO stacks */
        smsc->unsent_mt = fifo_new();
        if(smsc->unsent_mt == NULL) goto error;
 
        smsc->sent_mt = fifo_new();
        if(smsc->sent_mt == NULL) goto error;
 
        smsc->delivered_mt = fifo_new();
        if(smsc->delivered_mt == NULL) goto error;
 
        smsc->received_mo = fifo_new();
        if(smsc->received_mo == NULL) goto error;
 
        smsc->fifo_t_in = fifo_new();
        if(smsc->fifo_t_in == NULL) goto error;
 
        smsc->fifo_t_out = fifo_new();
        if(smsc->fifo_t_out == NULL) goto error;
 
        smsc->fifo_r_in = fifo_new();
        if(smsc->fifo_r_in == NULL) goto error;
 
        smsc->fifo_r_out = fifo_new();
        if(smsc->fifo_r_out == NULL) goto error;
 
        /* Create buffers */
        smsc->data_t = data_new();
        if(smsc->data_t == NULL) goto error;
        
        smsc->data_r = data_new();
        if(smsc->data_r == NULL) goto error;
 
        /* Open the transmitter connection */
        smsc->fd_t = tcpip_connect_to_server(smsc->hostname, smsc->port);
        if(smsc->fd_t == -1) goto error;
        smsc->smpp_t_state = SMPP_STATE_CONNECTED;
 
        /* Open the receiver connection */
        smsc->fd_r = tcpip_connect_to_server(smsc->hostname, smsc->port);
        if(smsc->fd_r == -1) goto error;
        smsc->smpp_r_state = SMPP_STATE_CONNECTED;
 
        /* Push a BIND_RECEIVER PDU on the [smsc->unsent] stack. */
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        pdu->id = SMPP_BIND_RECEIVER;
        smsc->seq_r = 1;
        pdu->sequence_no = 1;
        bind_receiver = malloc(sizeof(struct smpp_pdu_bind_receiver));
        if(bind_receiver==NULL) goto error;
        memset(bind_receiver, 0, sizeof(struct smpp_pdu_bind_receiver));
        strncpy(bind_receiver->system_id, smsc->smpp_system_id, 16);
        strncpy(bind_receiver->password, smsc->smpp_password, 9);
        strncpy(bind_receiver->system_type, smsc->smpp_system_type, 13);
        strncpy(bind_receiver->address_range, smsc->smpp_address_range, 41);
        pdu->message_body = bind_receiver;
        fifo_push(smsc->fifo_r_out, pdu);
        
        /* Push a BIND_TRANSMITTER PDU on the [smsc->unsent] stack. */
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        pdu->id = SMPP_BIND_TRANSMITTER;
        smsc->seq_t = 1;
        pdu->sequence_no = 1;
        bind_transmitter = malloc(sizeof(struct smpp_pdu_bind_transmitter));
        if(bind_transmitter==NULL) goto error;
        memset(bind_transmitter, 0, sizeof(struct smpp_pdu_bind_transmitter));
        strncpy(bind_transmitter->system_id, smsc->smpp_system_id, 16);
        strncpy(bind_transmitter->password, smsc->smpp_password, 9);
        strncpy(bind_transmitter->system_type, smsc->smpp_system_type, 13);
        strncpy(bind_transmitter->address_range, smsc->smpp_address_range, 41);
        pdu->message_body = bind_transmitter;
        fifo_push(smsc->fifo_t_out, pdu);
 
        /* Done, return */
        return 1;
 
error:
        error(0, "smpp_reopen: could not open");
 
        pdu_free(pdu);
 
        /* Destroy FIFO stacks. */
        fifo_free(smsc->unsent_mt);
        fifo_free(smsc->sent_mt);
        fifo_free(smsc->delivered_mt);
        fifo_free(smsc->received_mo);
        fifo_free(smsc->fifo_t_in);
        fifo_free(smsc->fifo_t_out);
        fifo_free(smsc->fifo_r_in);
        fifo_free(smsc->fifo_r_out);
 
        /* Destroy buffers */
        data_free(smsc->data_t);
        data_free(smsc->data_r);
 
        smscenter_destruct(smsc);
 
        return -1;
}
 
 
int smpp_close(SMSCenter *smsc) {
 
        struct smpp_pdu *pdu = NULL;
 
        /* Push a UNBIND PDU on the [smsc->fifo_r_out] stack. */
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        pdu->id = SMPP_UNBIND;
        pdu->length = 16;
        pdu->status = 0;
        pdu->sequence_no = 1;
        pdu->message_body = NULL;
        fifo_push(smsc->fifo_r_out, pdu);
        
        /* Push a UNBIND PDU on the [smsc->fifo_t_out] stack. */
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        pdu->id = SMPP_UNBIND;
        pdu->length = 16;
        pdu->status = 0;
        pdu->sequence_no = 1;
        pdu->message_body = NULL;
        fifo_push(smsc->fifo_t_out, pdu);
 
        /* Write out the UNBIND PDUs. */
        smpp_pending_smsmessage(smsc);
 
        /* Wait a while. */
        usleep(100);
 
        /* Check states */
 
#if 0
/*  XXX LATER, WHEN THIS IS IMPLEMENTED IN SMSGATEWAY.C XXX */
        /* If states are BOUND then push UNBIND messages to
           fifostack and return a failure. */
 
        if(smsc->smpp_t_state == 1)
               return 0;
 
        if(smsc->smpp_r_state == 1)
               return 0;
#endif
 
        /* Close transmitter connection. */
        close(smsc->fd_t);
 
        /* Close receiver connection. */
        close(smsc->fd_r);
 
        /* Destroy FIFO stacks. */
        fifo_free(smsc->unsent_mt);
        fifo_free(smsc->sent_mt);
        fifo_free(smsc->delivered_mt);
        fifo_free(smsc->received_mo);
        fifo_free(smsc->fifo_t_in);
        fifo_free(smsc->fifo_t_out);
        fifo_free(smsc->fifo_r_in);
        fifo_free(smsc->fifo_r_out);
 
        /* Destroy buffers */
        data_free(smsc->data_t);
        data_free(smsc->data_r);
 
        return 0;
 
error:
        return -1;
}
 
int smpp_submit_smsmessage(SMSCenter *smsc, SMSMessage *msg) {
 
        struct smpp_pdu *pdu = NULL;
        struct smpp_pdu_submit_sm *submit_sm = NULL;
 
        /* Validate *msg. */
        if(smsc == NULL) goto error;
        if(msg == NULL) goto error;
 
        /* If we cannot really send yet, push message to
           smsc->unsent_mt where it will stay until
           smpp_pdu_act_bind_transmitter_resp is called. */
 
        if( smsc->smpp_t_state != SMPP_STATE_BOUND ) {
               fifo_push_smsmessage(smsc->unsent_mt, msg);
               return 1;
        }
 
        /* Push a SUBMIT_SM PDU on the smsc->fifo_t_out fifostack. */
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        memset(pdu, 0, sizeof(struct smpp_pdu));
 
        submit_sm = malloc(sizeof(struct smpp_pdu_submit_sm));
        if(submit_sm == NULL) goto error;
        memset(submit_sm, 0, sizeof(struct smpp_pdu_submit_sm));
 
        strncpy(submit_sm->source_addr, msg->sender, 21);
        submit_sm->source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
        submit_sm->source_addr_ton = GSM_ADDR_TON_NETWORKSPECIFIC;
 
        /* Notice that the +2 is to get rid of the 00 start. */
        strncat(submit_sm->dest_addr, msg->receiver+2, 21);
        submit_sm->dest_addr_npi = GSM_ADDR_NPI_E164;
        submit_sm->dest_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
 
        submit_sm->data_coding = 3;
 
        submit_sm->sm_length = octstr_len(msg->text);
        octstr_get_many_chars(submit_sm->short_message, msg->text, 0, 160);
        charset_iso_to_smpp(submit_sm->short_message);
 
        pdu->id = SMPP_SUBMIT_SM;
        pdu->status = 0;
        pdu->sequence_no = smsc->seq_t++;
        pdu->message_body = submit_sm;
        pdu->length = 16 + 
               strlen(submit_sm->service_type) + 1 +
               1 + 1 +
               strlen(submit_sm->source_addr) + 1 +
               1 + 1 +
               strlen(submit_sm->dest_addr) + 1 +
               1 + 1 + 1 +
               strlen(submit_sm->schedule_delivery_time) + 1 +
               strlen(submit_sm->validity_period) + 1 +
               1 + 1 + 1 + 1 + 1 +
               strlen(submit_sm->short_message) + 1;
 
        fifo_push(smsc->fifo_t_out, pdu);
 
        return 0;
 
error:
        return -1;
}
 
 
int smpp_receive_smsmessage(SMSCenter *smsc, SMSMessage **msg) {
 
        SMSMessage *newmsg = NULL;
        char *newnum = NULL;
 
        /* Pop a SMSMessage message from the MSG_MO stack. */
        if( fifo_pop_smsmessage(smsc->received_mo, &newmsg) == 1 ) {
 
               /* Change the number format on msg->sender. */
               newnum = malloc(strlen(newmsg->sender)+3);
               if(newnum==NULL) goto error;
               memset(newnum, 0, strlen(newmsg->sender)+3);
               strcpy(newnum, "00");
               strcat(newnum, newmsg->sender);
               free(newmsg->sender);
               newmsg->sender = newnum;
 
               *msg = newmsg;
 
               return 1;
        }
        
        return 0;
error:
        error(errno, "smpp_receive_smsmessage: error");
        return -1;
}
 
int smpp_pending_smsmessage(SMSCenter *smsc) {
 
        Octstr *data = NULL;
        smpp_pdu *pdu = NULL;
        int ret = 0, funcret = 0;
 
        /* Process the MT messages. */
 
        /* Send whatever we need to send */
        while( fifo_pop(smsc->fifo_t_out, &pdu) == 1 ) {
               /* Encode the PDU to raw data. */
               if( pdu_encode(pdu, &data) == 1 ) {
                       /* Send the PDU data. */
                       ret = data_send(smsc->fd_t, data);
                       data_free(data);
                       if(ret==-1) break;
               }
               pdu_free(pdu);
               if(ret==-1) break;
        }
 
        /* Receive raw data */
        ret = data_receive(smsc->fd_t, smsc->data_t);
        if(ret == -1) {
               warning(0, "smpp_pending_smsmessage: reopening connections");
               smpp_reopen(smsc);
        }
 
        /* Interpret the raw data */
        while( data_pop(smsc->data_t, &data) == 1 ) { 
               /* Decode the PDU from raw data. */
               if( (ret = pdu_decode(&pdu, data)) ) {
                       /* Act on PDU. */
                       pdu->fd = smsc->fd_t;
                       ret = pdu_act(smsc, pdu);
                       pdu_free(pdu);
               }
               data_free(data);
        }
 
        /* Process the MO messages. */
 
        ret = data_receive(smsc->fd_r, smsc->data_r);
        if(ret == -1) {
               warning(0, "smpp_pending_smsmessage: reopening connections");
               smpp_reopen(smsc);
        }
 
        while( fifo_pop(smsc->fifo_r_out, &pdu) == 1 ) {
               /* Encode the PDU to raw data. */
               if( (ret = pdu_encode(pdu, &data)) ) {
                       /* Send the PDU data. */
                       ret = data_send(smsc->fd_r, data);
                       data_free(data);
                       if(ret==-1) break;
               }
               pdu_free(pdu);
               if(ret==-1) break;
        }
 
        while( data_pop(smsc->data_r, &data) == 1 ) {
               /* Decode the PDU from raw data. */
               if( (ret = pdu_decode(&pdu, data)) ) {
                       /* Act on PDU. */
                       pdu->fd = smsc->fd_r;
                       ret = pdu_act(smsc, pdu);
                       pdu_free(pdu);
               }
               data_free(data);
        }
 
        /* Signal that we got a MO message */
        if(smsc->received_mo->left != NULL) funcret = 1;
 
        /* If it's been a "long time" (defined elsewhere) since
           the last message, actively check the link status by
           sending a LINK_STATUS pdu to the SMSC, thereby 
           (maybe) resetting the close-if-no-traffic timer.
           Note: in practise we won't need this. */
 
        /* XXX DO IT */
 
        return funcret;
}
 
static smpp_pdu* pdu_new(void) {
 
        struct smpp_pdu *newpdu = NULL;
 
        newpdu = malloc(sizeof(struct smpp_pdu));
        memset(newpdu, 0, sizeof(struct smpp_pdu));
 
        return newpdu;
}
 
static int pdu_free(smpp_pdu *pdu) {
 
        if(pdu == NULL) return 0;
 
        smsmessage_destruct(pdu->smsmsg);
        free(pdu->message_body);
        free(pdu);
 
        return 1;
}
 
static Octstr* data_new(void) {
 
        struct Octstr *newstr = NULL;
 
        newstr = octstr_create_empty();
 
        return newstr;
}
 
static int data_free(Octstr *str) {
 
        if(str == NULL) return 0;
 
        octstr_destroy(str);
 
        return 1;
}
 
static fifostack* fifo_new(void) {
 
        struct fifostack *newfifo = NULL;
 
        newfifo = malloc(sizeof(struct fifostack));
        if(newfifo == NULL) goto error;
        memset(newfifo, 0, sizeof(struct fifostack));
 
        return newfifo;
 
error:
        error(0, "fifo_new: memory allocation error");
        return NULL;
}
 
static void fifo_free(fifostack *fifo) {
 
        struct smpp_pdu *pdu = NULL;
 
        if(fifo == NULL) return;
 
        /* Drain the leftover PDUs to the bit sink. */
        while( fifo_pop(fifo, &pdu) == 1 )  {
               pdu_free(pdu);
               pdu = NULL;
        }
 
        free(fifo);
 
        return;
}
 
static int fifo_push(fifostack *fifo, smpp_pdu *pdu) {
 
        if(fifo == NULL) {
               error(0, "fifo_push: NULL input");
               goto error;
        }
 
        if(pdu == NULL) {
               error(0, "fifo_push: NULL input");
               goto error;
        }
 
        /* If fifostack is completely empty. */
        if( (fifo->left == NULL) && (fifo->right == NULL) ) {
               fifo->left = pdu;
               fifo->right = pdu;
               pdu->left = NULL;
               pdu->right = NULL;
               goto a_ok;
        }
 
        /* Ok, insert the pdu on the left side. */
        pdu->left = NULL;
        (fifo->left)->left = pdu;
        fifo->left = pdu;
 
a_ok:
        return 1;
error:
        error(0, "fifo_push: error");
        return -1;
 
}
 
static int fifo_pop(fifostack *fifo, smpp_pdu **pdu) {
 
        if(fifo == NULL) {
               error(0, "fifo_pop: NULL input");
               goto error;
        }
 
        if(pdu == NULL) {
               error(0, "fifo_pop: NULL input");
               goto error;
        }
 
        /* If fifostack is completely empty. */
        if( (fifo->left == NULL) && (fifo->right == NULL) ) {
               goto no_msgs;
        }
 
        /* Drop a message from the right side. */
        *pdu = fifo->right;
 
        /* If this was the last PDU and the fifostack is now empty. */
        if(fifo->right->left == NULL) {
               fifo->right = NULL;
               fifo->left = NULL;
        } else {
               /* Set the new right edge. */
               fifo->right = (fifo->right)->left;
               /* Terminate. */
               (fifo->right)->right = NULL;
        }
 
        return 1;
 
no_msgs:
        return 0;
 
error:
        error(0, "fifo_pop: returing error");
        return -1;
}
 
static int fifo_push_smsmessage(fifostack *fifo, SMSMessage *msg) {
 
        struct smpp_pdu *pdu = NULL;
 
        pdu = pdu_new();
        if(pdu == NULL) goto error;
        memset(pdu, 0, sizeof(struct smpp_pdu));
        
        pdu->smsmsg = msg;
        fifo_push(fifo, pdu);
 
        return 1;
 
error:
        error(0, "fifo_push_smsmessage: returning error");
        return -1;
}
 
static int fifo_pop_smsmessage(fifostack *fifo, SMSMessage **msg) {
 
        struct smpp_pdu *pdu = NULL;
        int ret;
 
        ret = fifo_pop(fifo, &pdu);
        if(ret == 0) goto no_msg;
        if(ret <>
 
        *msg = pdu->smsmsg;
        if(*msg == NULL) goto error;
 
        pdu->smsmsg = NULL;
        pdu_free(pdu);
 
        return 1;
 
no_msg:
        return 0;
 
error:
        error(0, "fifo_pop_smsmessage: returning error");
        return -1;
}
 
 
/******************************************************************************
* data_pop
*
*  from: The Octstr to cut from
*  to: The Octstr to create and paste to
*
* Description:
*  
* Returns:
*  1 if a PDU was found
*  0 if no PDU found
* -1 if an error occurred
*
*/
static int data_pop(Octstr *from, Octstr **to) {
 
        int32 quadoct;
        int32 realint;
        unsigned int olen = 0;
 
        olen = octstr_len(from);
 
        /* Check if [from] has enough data to contain a PDU (>=16 octets) */
        if(olen <>
 
        /* Read the length (4 first octets) */
        octstr_get_many_chars((char*)&quadoct, from, 0, 4);
 
        /* Translate the length XXX MAKE THIS INTO 1 FUNCTION */
        realint = ntohl(quadoct);
 
        /* Check if we have [length] octets of data */
        if(olen <>
 
        /* Cut the PDU out, move data to fill the hole. */
        *to = octstr_copy(from, 0, realint);
        if(*to == NULL) goto error;
        octstr_delete(from, 0, realint);
 
        /* Okay, done */
        return 1;
 
no_msg:
        *to = NULL;
        return -1;
 
error:
        error(0, "data_pop: ERROR!!!");
        *to = NULL;
        return -1;
}
 
/******************************************************************************
* data_receive
*
*  fd: the File Descriptor to read from
*  to: The Octstr to append to
*
* Description:
*  Receive data from [fd] and append it to [to].
*  
* Returns:
*  1 if a PDU was found
*  0 if no PDU found
* -1 if an error occurred
*
*/
static int data_receive(int fd, Octstr *to) {
 
        size_t length;
        char   data[1024];
        Octstr *newstr = NULL;
 
        fd_set rf;
        struct timeval tox;
        int ret;
 
        memset(&data, 0, sizeof(data));
 
        FD_ZERO(&rf);
        FD_SET(fd, &rf);
        tox.tv_sec = 0;
        tox.tv_usec = 100;
        ret = select(FD_SETSIZE, &rf, NULL, NULL, &tox);
 
        if (ret == 0) {
               goto no_data;
        } else if (ret <>
               if(errno == EBADF) {
                       error(errno, "data_receive: select failed");
               }
               goto error;
        }
 
        /* Create temp data structures. */
        length = read(fd, &data, sizeof(data)-1);
 
        if(length == -1) {
/*             if(errno==EWOULDBLOCK) return -1; */
               goto error;
        } else if(length == 0) {
               debug(0, "soketti <%i> kloused", fd);
               goto error;
        }
 
        newstr = octstr_create_from_data(data, length);
        
        if(newstr == NULL) goto error;
        octstr_insert(to, newstr, octstr_len(to));
 
        /* Okay, done */
        return 1;
 
no_data:
        return 0;
 
error:
        debug(0, "data_receive: error");
        return -1;
}
 
/******************************************************************************
* data_send
*
*  fd: the File Descriptor to write to
*  to: The Octstr to get the data from
*
* Description:
*  Write all the data from [from] to [fd].
*  
* Returns:
*  1 if a PDU was found
*  0 if no PDU found
* -1 if an error occurred
*
*/
static int data_send(int fd, Octstr *from) {
 
        size_t length, curl, written = 0;
        char *willy = NULL;
 
        debug(0, "data_send: starting");
 
        /* Create temp data structures. */
        length = octstr_len(from);
        if(length <= 0) return 0;
 
        willy = malloc(length);
        if(willy == NULL) goto error;
 
        octstr_get_many_chars(willy, from, 0, length);
 
        /* Write to socket */
        for(;;) {
               if(written >= length) break;
               curl = write(fd, willy+written, length-written);
               if(curl == -1) {
                       if(errno==EAGAIN) continue;
                       if(errno==EINTR) continue;
                       if(errno==EBADF) {
                               error(errno, "data_send: write(2) failed");
                       }
                       goto error;
               } else if(curl == 0) {
                       goto socket_b0rken;
               }
               written += curl;
        }
 
        /* Okay, done */
        free(willy);
        return 1;
 
socket_b0rken:
        debug(0, "data_send: broken socket!!!");
        free(willy);
        return -1;
 
error:
        debug(0, "data_send: ERROR!!!");
        free(willy);
        return -1;
}
 
/* Append a single octet of data. Update where to reflect the
   next byte to write to, decrease left by the number of
   bytes written. */
static int smpp_append_oct(char** where, int* left, uint32_t data) {
 
/* Change this to reflect differences in endianness and
   bytenesses. */
#if BYTE_ORDER == LITTLE_ENDIAN
        memcpy(*where, &data, 1);
        *where += 1;
#elif BYTE_ORDER == BIG_ENDIAN
        memcpy(*where, (&data)+3, 1);
        *where += 1;
#else
        /* We have to write another section here for PDPs :) */
        error(0, "smpp_append_oct: wrong endianness.");
#endif
 
        return 1;
}
 
static int smpp_read_oct(char** where, int* left, Octet* data) {
        return -1;
        smpp_read_oct(where, left, data);
}
 
static int smpp_append_cstr(char** where, int* left, char* data) {
 
        memcpy(*where, data, strlen(data)+1);
        *where += (strlen(data) + 1);
 
        return 1;
}
 
static int smpp_read_cstr(char** where, int* left, char** data) {
        return -1;
        smpp_read_cstr(where, left, data);
}
 
static int smpp_append_int32(char** where, int* left, int32 data) {
        return -1;
        smpp_append_int32(where, left, data);
}
 
static int smpp_read_int32(char** where, int* left, int32* data) {
        return -1;
        smpp_read_int32(where, left, data);
}
 
 
/******************************************************************************
* pdu_act
*
*  Decide what to do with a PDU once we have managed to obtain one.
*
* Refer to:
*  SMPP 3.3 specification section 5.5.2
*
* Returns:
*  1 if a PDU was found
*  0 if no PDU found
* -1 if an error occurred
*
*/
static int pdu_act(SMSCenter *smsc, smpp_pdu *pdu) {
 
        int ret = -1;
 
        switch(pdu->id) {
 
        case SMPP_BIND_RECEIVER_RESP:
               ret = pdu_act_bind_receiver_resp(smsc, pdu);
               break;
 
        case SMPP_BIND_TRANSMITTER_RESP:
               ret = pdu_act_bind_transmitter_resp(smsc, pdu);
               break;
 
        case SMPP_UNBIND_RESP:
               ret = pdu_act_unbind_resp(smsc, pdu);
               break;
 
        case SMPP_SUBMIT_SM_RESP:
               ret = pdu_act_submit_sm_resp(smsc, pdu);
               break;
 
        case SMPP_SUBMIT_MULTI_RESP:
               ret = pdu_act_submit_multi_resp(smsc, pdu);
               break;
 
        case SMPP_DELIVER_SM:
               ret = pdu_act_deliver_sm(smsc, pdu);
               break;
 
        case SMPP_QUERY_SM_RESP:
               ret = pdu_act_query_sm_resp(smsc, pdu);
               break;
 
        case SMPP_CANCEL_SM_RESP:
               ret = pdu_act_cancel_sm_resp(smsc, pdu);
               break;
 
        case SMPP_REPLACE_SM_RESP:
               ret = pdu_act_replace_sm_resp(smsc, pdu);
               break;
 
        case SMPP_ENQUIRE_LINK:
               ret = pdu_act_enquire_link(smsc, pdu);
               break;
 
        case SMPP_ENQUIRE_LINK_RESP:
               ret = pdu_act_enquire_link_resp(smsc, pdu);
               break;
 
        case SMPP_GENERIC_NAK:
               ret = pdu_act_generic_nak(smsc, pdu);
               break;
 
/*      case SMPP_QUERY_LAST_MSGS_RESP:
               ret = pdu_act_query_last_msgs_resp(smsc, pdu);
               break;
 
        case SMPP_QUERY_MSG_DETAILS_RESP:
               ret = pdu_act_query_msg_details_resp(smsc, pdu);
               break;
*/
        }
 
        return ret;
}
 
 
/******************************************************************************
* pdu_decode
*
* Description:
*  Decode given raw data into a brand new SMPP PDU.
*
* Returns:
*  1 if a PDU was created
*  0 if no PDU could be created
* -1 if an error occurred
*
*/
static int pdu_decode(smpp_pdu **pdu, Octstr *from) {
 
        int ret;
        struct smpp_pdu *newpdu;
 
        newpdu = pdu_new();
 
        /* Decode the header */
        ret = pdu_header_decode(newpdu, from);
 
        switch(newpdu->id) {
        
        case SMPP_BIND_RECEIVER_RESP:
               ret = pdu_decode_bind(newpdu, from);
               break;
 
        case SMPP_BIND_TRANSMITTER_RESP:
               ret = pdu_decode_bind(newpdu, from);
               break;
 
        case SMPP_UNBIND_RESP:
               ret = pdu_decode_bind(newpdu, from);
               break;
 
        case SMPP_DELIVER_SM:
               ret = pdu_decode_deliver_sm(newpdu, from);
               break;
 
        case SMPP_SUBMIT_SM_RESP:
               ret = pdu_decode_submit_sm_resp(newpdu, from);
               break;
#if 0
 
        case SMPP_SUBMIT_MULTI_RESP:
               ret = pdu_decode_submit_multi_resp(smsc, pdu);
               break;
 
        case SMPP_QUERY_SM_RESP:
               ret = pdu_decode_query_sm_resp(smsc, pdu);
               break;
 
/*
        case SMPP_QUERY_LAST_MSGS_RESP:
               ret = pdu_decode_query_last_msgs_resp(smsc, pdu);
               break;
 
        case SMPP_QUERY_MSG_DETAILS_RESP:
               ret = pdu_decode_query_msg_details_resp(smsc, pdu);
               break;
*/
 
        case SMPP_CANCEL_SM_RESP:
               ret = pdu_decode_cancel_sm_resp(smsc, pdu);
               break;
 
        case SMPP_REPLACE_SM_RESP:
               ret = pdu_decode_replace_sm_resp(smsc, pdu);
               break;
 
        case SMPP_ENQUIRE_LINK:
               ret = pdu_decode_enquire_link(smsc, pdu);
               break;
 
        case SMPP_ENQUIRE_LINK_RESP:
               ret = pdu_decode_enquire_link_resp(smsc, pdu);
               break;
 
        case SMPP_GENERIC_NAK:
               ret = pdu_decode_generic_nak(smsc, pdu);
               break;
#endif
        }
 
        *pdu = newpdu;
 
        return 1;
 
}
 
/******************************************************************************
* pdu_encode
*
* Description:
*  Encode a given SMPP PDU structure to raw data.
*
* Returns:
*  1 if PDU was translated to raw data
*  0 if PDU couldn't be translated
* -1 if an error occurred
*
*/
static int pdu_encode(smpp_pdu *pdu, Octstr **rawdata) {
 
        struct Octstr *body = NULL, *header = NULL, *whole = NULL;
        int ret;
 
        switch(pdu->id) {
 
        case SMPP_BIND_RECEIVER:
               ret = pdu_encode_bind(pdu, &body);
               break;
 
        case SMPP_BIND_RECEIVER_RESP:
               ret = pdu_encode_bind(pdu, &body);
               break;
 
        case SMPP_BIND_TRANSMITTER:
               ret = pdu_encode_bind(pdu, &body);
               break;
 
        case SMPP_BIND_TRANSMITTER_RESP:
               ret = pdu_encode_bind(pdu, &body);
               break;
 
        case SMPP_UNBIND_RESP:
               ret = pdu_encode_bind(pdu, &body);
               break;
 
        case SMPP_DELIVER_SM_RESP:
               ret = pdu_encode_deliver_sm_resp(pdu, &body);
               break;
 
        case SMPP_SUBMIT_SM:
               ret = pdu_encode_submit_sm(pdu, &body);
               break;
 
#if 0
        case SMPP_SUBMIT_MULTI:
               ret = pdu_encode_submit_multi(pdu, &body);
               break;
 
        case SMPP_QUERY_SM:
               ret = pdu_encode_query_sm(pdu, &body);
               break;
 
/*
        case SMPP_QUERY_LAST_MSGS:
               ret = pdu_encode_query_last_msgs(pdu, &body);
               break;
 
        case SMPP_QUERY_MSG_DETAILS:
               ret = pdu_encode_query_msg_details(pdu, &body);
               break;
*/
 
        case SMPP_CANCEL_SM:
               ret = pdu_encode_cancel_sm(pdu, &body);
               break;
 
        case SMPP_REPLACE_SM:
               ret = pdu_encode_replace_sm(pdu, &body);
               break;
 
        case SMPP_ENQUIRE_LINK:
               ret = pdu_encode_enquire_link(pdu, &body);
               break;
 
        case SMPP_ENQUIRE_LINK_RESP:
               ret = pdu_encode_enquire_link_resp(pdu, &body);
               break;
 
        case SMPP_GENERIC_NAK:
               ret = pdu_encode_generic_nak(pdu, &body);
               break;
#endif
 
        }
 
        pdu_header_encode(pdu, &header);
 
        whole = octstr_cat(header, body);
 
        octstr_destroy(header);
        octstr_destroy(body);
 
        *rawdata = whole;
 
        return 1;
}
 
 
static int pdu_header_decode(smpp_pdu *pdu, Octstr *str) {
 
        uint32_t header[4];
 
        if(pdu == NULL) goto error;
        if(str == NULL) goto error;
 
        /* Read the header */
        octstr_get_many_chars((char*)&header, str, 0, sizeof(header));
 
        pdu->length = ntohl(header[0]);
        pdu->id     = ntohl(header[1]);
        pdu->status = ntohl(header[2]);
        pdu->sequence_no = ntohl(header[3]);
 
        return 1;
 
error:
        return -1;
}
 
static int pdu_header_encode(smpp_pdu *pdu, Octstr **rawdata) {
 
        uint32_t length, id, status, seq;
 
        Octstr *newdata = NULL;
        char temp[16], *tempptr;
 
        memset(temp, 0, sizeof(temp));
 
        tempptr = temp;
 
        length = htonl(pdu->length);
        id     = htonl(pdu->id);
        status = htonl(pdu->status);
        seq    = htonl(pdu->sequence_no);
 
        memcpy(tempptr, &length, 4);
        tempptr += 4;
        
        memcpy(tempptr, &id, 4);
        tempptr += 4;
 
        memcpy(tempptr, &status, 4);
        tempptr += 4;
 
        memcpy(tempptr, &seq, 4);
        tempptr += 4;
 
        newdata = octstr_create_from_data(temp, sizeof(temp));
 
        *rawdata = newdata;
 
        return 1;
}
 
static int pdu_decode_bind(smpp_pdu *pdu, Octstr *str) {
 
        return 1;
}
 
static int pdu_encode_bind(smpp_pdu *pdu, Octstr **str) {
 
        int length = 0;
        char *data = NULL, *where = NULL;
        Octstr *body_encoded;
        int left;
        
        struct smpp_pdu_bind_receiver *bind_receiver;
        struct smpp_pdu_bind_receiver_resp *bind_receiver_resp;
        struct smpp_pdu_bind_transmitter *bind_transmitter;
        struct smpp_pdu_bind_transmitter_resp *bind_transmitter_resp;
 
        switch(pdu->id) {
 
        case SMPP_BIND_RECEIVER:
               bind_receiver = (smpp_pdu_bind_receiver*) pdu->message_body;
               length = strlen(bind_receiver->system_id) + 1 +
                        strlen(bind_receiver->password) + 1 +
                        strlen(bind_receiver->system_type) + 1 +
                        1 + 1 + 1 +
                        strlen(bind_receiver->address_range) + 1;
               data = malloc(length);
               if(data == NULL) goto error;
               memset(data, 0, length);
               where = data;
 
               smpp_append_cstr(&where, &left, bind_receiver->system_id);
               smpp_append_cstr(&where, &left, bind_receiver->password);
               smpp_append_cstr(&where, &left, bind_receiver->system_type);
               smpp_append_oct(&where, &left, bind_receiver->interface_version);
               smpp_append_oct(&where, &left, bind_receiver->addr_ton);
               smpp_append_oct(&where, &left, bind_receiver->addr_npi);
               smpp_append_cstr(&where, &left, bind_receiver->address_range);
 
               break;
 
        case SMPP_BIND_RECEIVER_RESP:
               length = strlen(bind_receiver_resp->system_id) + 1;
               data = malloc(length);
               if(data == NULL) goto error;
               memset(data, 0, length);
               where = data;
 
               smpp_append_cstr(&where, &left, bind_receiver_resp->system_id);
 
               break;
 
        case SMPP_BIND_TRANSMITTER:
               bind_transmitter = (smpp_pdu_bind_transmitter*) pdu->message_body;
               length = strlen(bind_transmitter->system_id) + 1 +
                        strlen(bind_transmitter->password) + 1 +
                        strlen(bind_transmitter->system_type) + 1 +
                        1 + 1 + 1 +
                        strlen(bind_transmitter->address_range) + 1;
 
               data = malloc(length);
               if(data == NULL) goto error;
               memset(data, 0, length);
               where = data;
 
               smpp_append_cstr(&where, &left, bind_transmitter->system_id);
               smpp_append_cstr(&where, &left, bind_transmitter->password);
               smpp_append_cstr(&where, &left, bind_transmitter->system_type);
               smpp_append_oct(&where, &left, bind_transmitter->interface_version);
               smpp_append_oct(&where, &left, bind_transmitter->addr_ton);
               smpp_append_oct(&where, &left, bind_transmitter->addr_npi);
                smpp_append_cstr(&where, &left, bind_transmitter->address_range);
 
               break;
 
        case SMPP_BIND_TRANSMITTER_RESP:
               bind_transmitter_resp = (smpp_pdu_bind_transmitter_resp*) pdu->message_body;
               length = strlen(bind_transmitter_resp->system_id) + 1;
               data = malloc(length);
               if(data == NULL) goto error;
 
               smpp_append_cstr(&where, &left, bind_transmitter_resp->system_id);
 
               break;
 
        case SMPP_UNBIND:
               data = NULL;
               length = 0;
               break;
 
        case SMPP_UNBIND_RESP:
               data = NULL;
               length = 0;
               break;
 
        }
 
        pdu->length = length + 16;
 
        body_encoded = octstr_create_from_data(data, length);
 
        *str = body_encoded;
 
        free(data);
 
        return 1;
error:
        return -1;
}
 
/******************************************************************************
* PDUs
*  BIND_TRANSMITTER, BIND_TRANSMITTER_RESP
*/
static int pdu_act_bind_transmitter_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        struct smpp_pdu *newpdu = NULL;
        struct smpp_pdu_submit_sm *submit_sm = NULL;
        SMSMessage *msg = NULL;
 
        /* Validate *msg. */
        if(smsc == NULL) goto error;
        if(pdu == NULL) goto error;
 
        smsc->smpp_t_state = SMPP_STATE_BOUND;
 
        /* Process any messages that were sent through the HTTP
           interface while the transmitter connection was not
           bound. */
        while( fifo_pop_smsmessage(smsc->unsent_mt, &msg) == 1 ) {
 
               /* Push a SUBMIT_SM PDU on the smsc->fifo_t_out fifostack. */
               newpdu = pdu_new();
               if(newpdu == NULL) goto error;
               memset(newpdu, 0, sizeof(struct smpp_pdu));
 
               submit_sm = malloc(sizeof(struct smpp_pdu_submit_sm));
               if(submit_sm == NULL) goto error;
               memset(submit_sm, 0, sizeof(struct smpp_pdu_submit_sm));
 
               strncpy(submit_sm->source_addr, msg->sender, 21);
               submit_sm->source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
               submit_sm->source_addr_ton = GSM_ADDR_TON_NETWORKSPECIFIC;
 
               /* Notice that the +2 is to get rid of the 00 start. */
               strncat(submit_sm->dest_addr, msg->receiver+2, 21);
               submit_sm->dest_addr_npi = GSM_ADDR_NPI_E164;
               submit_sm->dest_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
 
               submit_sm->data_coding = 3;
 
               submit_sm->sm_length = octstr_len(msg->text);
               octstr_get_many_chars(submit_sm->short_message, msg->text, 0, 160);
               charset_iso_to_smpp(submit_sm->short_message);
 
               newpdu->id = SMPP_SUBMIT_SM;
               newpdu->status = 0;
               newpdu->sequence_no = smsc->seq_t++;
               newpdu->message_body = submit_sm;
               newpdu->length = 16 + 
                       strlen(submit_sm->service_type) + 1 +
                       1 + 1 +
                       strlen(submit_sm->source_addr) + 1 +
                       1 + 1 +
                       strlen(submit_sm->dest_addr) + 1 +
                       1 + 1 + 1 +
                       strlen(submit_sm->schedule_delivery_time) + 1 +
                       strlen(submit_sm->validity_period) + 1 +
                       1 + 1 + 1 + 1 + 1 +
                       strlen(submit_sm->short_message) + 1;
 
               fifo_push(smsc->fifo_t_out, newpdu);
 
        }
 
        return 0;
 
error:
        return -1;
}
 
/******************************************************************************
* PDUs
*  BIND_RECEIVER, BIND_RECEIVER_RESP
*/
static int pdu_act_bind_receiver_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        smsc->smpp_r_state = SMPP_STATE_BOUND;
 
        return 1;
}
 
/******************************************************************************
* PDUs
*  UNBIND, UNBIND_RESP
*/
static int pdu_act_unbind_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
/*      debug(0, "pdu_act_unbind_resp: start"); */
 
        /* Remove the status flag CAN_RECEIVE or CAN_SEND */
 
        return -1;
}
 
/******************************************************************************
* PDUs
*  SUBMIT_SM, SUBMIT_SM_RESP
*/
static int pdu_act_submit_sm_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        debug(0, "pdu_act_submit_sm_resp: start");
 
        /* Mark message the SUBMIT_SM_RESP refers to as 
           acknowledged and remove it from smsc->smpp_fifostack. */
 
        debug(0, "pdu->length == %08x", pdu->length);
        debug(0, "pdu->id == %08x", pdu->id);
        debug(0, "pdu->status == %08x", pdu->status);
        debug(0, "pdu->sequence_no == %08x", pdu->sequence_no);
 
        return -1;
}
 
static int pdu_encode_submit_sm(smpp_pdu* pdu, Octstr** str) {
 
        struct smpp_pdu_submit_sm *submit_sm = NULL;
 
        int32 length;
        int left;
        char *data = NULL, *where = NULL;
        Octstr *newstr = NULL;
 
        submit_sm = (struct smpp_pdu_submit_sm*) pdu->message_body;
 
        length = strlen(submit_sm->service_type) + 1 +
                1 + 1 +
                strlen(submit_sm->source_addr) + 1 +
                1 + 1 +
                strlen(submit_sm->dest_addr) + 1 +
                1 + 1 + 1 +
                strlen(submit_sm->schedule_delivery_time) + 1 +
                strlen(submit_sm->validity_period) + 1 +
                1 + 1 + 1 + 1 + 1 +
                strlen(submit_sm->short_message) + 1;
 
        data = malloc(length);
        if(data == NULL) goto error;
        memset(data, 0, length);
        where = data;
 
        smpp_append_cstr(&where, &left, submit_sm->service_type);
        smpp_append_oct(&where, &left, submit_sm->source_addr_ton);
        smpp_append_oct(&where, &left, submit_sm->source_addr_npi);
        smpp_append_cstr(&where, &left, submit_sm->source_addr);
        smpp_append_oct(&where, &left, submit_sm->dest_addr_ton);
        smpp_append_oct(&where, &left, submit_sm->dest_addr_npi);
        smpp_append_cstr(&where, &left, submit_sm->dest_addr);
        smpp_append_oct(&where, &left, submit_sm->esm_class);
        smpp_append_oct(&where, &left, submit_sm->protocol_id);
        smpp_append_oct(&where, &left, submit_sm->priority_flag);
        smpp_append_cstr(&where, &left, submit_sm->schedule_delivery_time);
        smpp_append_cstr(&where, &left, submit_sm->validity_period);
        smpp_append_oct(&where, &left, submit_sm->registered_delivery_flag);
        smpp_append_oct(&where, &left, submit_sm->replace_if_present_flag);
        smpp_append_oct(&where, &left, submit_sm->data_coding);
        smpp_append_oct(&where, &left, submit_sm->sm_default_msg_id);
        smpp_append_oct(&where, &left, submit_sm->sm_length);
        smpp_append_cstr(&where, &left, submit_sm->short_message);
 
        newstr = octstr_create_from_data(data, length);
 
        *str = newstr;
 
        return 1;
error:
        return -1;
}
 
static int pdu_decode_submit_sm_resp(smpp_pdu* pdu, Octstr* str) {
        return -1;
}
 
 
 
/******************************************************************************
* PDUs
*  SUBMIT_MULTI, SUBMIT_SM_MULTI_RESP
*/
static int pdu_act_submit_multi_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        debug(0, "pdu_act_submit_multi_resp: start");
 
        /* Mark messages reffer to by the SUBMIT_MULTI_RESP as
           acknowledged and remove them from smsc->fifostack. */
 
        return -1;
}
 
/******************************************************************************
* PDUs
*  DELIVER_SM, DELIVER_SM_RESP
*/
static int pdu_act_deliver_sm(SMSCenter *smsc, smpp_pdu *pdu) {
 
        struct smpp_pdu *newpdu = NULL;
        struct smpp_pdu_deliver_sm *deliver_sm = NULL;
        struct smpp_pdu_deliver_sm_resp *deliver_sm_resp = NULL;
 
        SMSMessage *smsmsg = NULL;
 
        /* If DELIVER_SM was sent to acknowledge that the terminal
           has received the message, ignore. */
        deliver_sm = (struct smpp_pdu_deliver_sm*) pdu->message_body;
        if(deliver_sm==NULL) goto error;
 
        /* Convert message from the Default Charset to ISO-8859-1. */
        charset_smpp_to_iso(deliver_sm->short_message);
 
        /* Convert the PDU into a SMSMessage structure. */
        smsmsg = smsmessage_construct(
               deliver_sm->source_addr, 
               deliver_sm->dest_addr,
               octstr_create(deliver_sm->short_message));
 
        /* Push the SMSMessage structure on the smsc->received_mo fifostack. */
        fifo_push_smsmessage(smsc->received_mo, smsmsg);
 
        /* Push a DELIVER_SM_RESP structure on the smsc->fifo_r_out fifostack. */
        newpdu = pdu_new();
        if(newpdu == NULL) goto error;
        memset(newpdu, 0, sizeof(struct smpp_pdu));
 
        deliver_sm_resp = malloc(sizeof(struct smpp_pdu_deliver_sm_resp));
        if(deliver_sm_resp == NULL) goto error;
        memset(deliver_sm_resp, 0, sizeof(struct smpp_pdu_deliver_sm_resp));
 
        newpdu->length = 17;
        newpdu->id = SMPP_DELIVER_SM_RESP;
        newpdu->status = 0;
        newpdu->sequence_no = pdu->sequence_no;
        newpdu->message_body = deliver_sm_resp;
 
        fifo_push(smsc->fifo_r_out, newpdu);
 
        return 1;
 
error:
        return -1;
}
 
static int pdu_encode_deliver_sm_resp(smpp_pdu *pdu, Octstr **str) {
 
        Octstr *newstr = NULL;
        struct smpp_pdu_deliver_sm_resp *deliver_sm_resp = NULL;
        char data;
 
        deliver_sm_resp = (struct smpp_pdu_deliver_sm_resp*) pdu->message_body;
 
        /* As specified in SMPP 3.3 / 6.3.3.2 */
        data = '\0';
 
        newstr = octstr_create_from_data(&data, 1);
 
        *str = newstr;
 
        return 1;
}
 
static int pdu_decode_deliver_sm(smpp_pdu* pdu, Octstr* str) {
 
        char *start, *end, *buff;
        struct smpp_pdu_deliver_sm *deliver_sm;
        Octet oct;
 
        if(pdu==NULL) goto error;
        if(str==NULL) goto error;
 
        if(octstr_len(str) <>
               warning(0, "pdu_decode_deliver_sm: incorrect input");
               goto error;
        }
 
        deliver_sm = malloc(sizeof(struct smpp_pdu_deliver_sm));
        if(deliver_sm==NULL) goto error;
        memset(deliver_sm, 0, sizeof(struct smpp_pdu_deliver_sm));
        pdu->message_body = deliver_sm;
 
        buff = malloc(octstr_len(str));
        if(buff == NULL) goto error;
 
        octstr_get_many_chars(buff, str, 0, octstr_len(str));
        start = buff + 16;
 
        end = start + strlen(start);
        strncpy(deliver_sm->service_type, start, 6);
        start = end+1;
 
        strncpy(&oct, start, 1);
        deliver_sm->source_addr_ton = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->source_addr_npi = oct;
        start++;
 
        end = start + strlen(start);
        strncpy(deliver_sm->source_addr, start, 21);
        start = end+1;
 
        strncpy(&oct, start, 1);
        deliver_sm->dest_addr_ton = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->dest_addr_npi = oct;
        start++;
 
        end = start + strlen(start);
        strncpy(deliver_sm->dest_addr, start, 21);
        start = end+1;
 
        strncpy(&oct, start, 1);
        deliver_sm->esm_class = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->protocol_id = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->priority_flag = oct;
        start++;
 
        end = start + strlen(start);
        strncpy(deliver_sm->schedule_delivery_time, start, 17);
        start = end+1;
 
        end = start + strlen(start);
        strncpy(deliver_sm->validity_period, start, 17);
        start = end+1;
 
        strncpy(&oct, start, 1);
        deliver_sm->registered_delivery_flag = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->replace_if_present_flag = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->data_coding = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->sm_default_msg_id = oct;
        start++;
 
        strncpy(&oct, start, 1);
        deliver_sm->sm_length = oct;
        start++;
 
        /* Make sure that the upcoming SMPP 3.4 implementation
           won't break our application with the new definition
           of max short_message size. */
        end = start + strlen(start);
        strncpy(deliver_sm->short_message, start, 
               (deliver_sm->sm_length > sizeof(deliver_sm->short_message)) ? 
                       sizeof(deliver_sm->short_message) : deliver_sm->sm_length);
        start = end+1;
 
        free(buff);
 
        debug(0, "pdu->service_type == %s", deliver_sm->service_type);
        
        debug(0, "pdu->source_addr_ton == %i", deliver_sm->source_addr_ton);
        debug(0, "pdu->source_addr_npi == %i", deliver_sm->source_addr_npi);
        debug(0, "pdu->source_addr == %s", deliver_sm->source_addr);
        
        debug(0, "pdu->dest_addr_ton == %i", deliver_sm->dest_addr_ton);
        debug(0, "pdu->dest_addr_npi == %i", deliver_sm->dest_addr_npi);
        debug(0, "pdu->dest_addr == %s", deliver_sm->dest_addr);
        
        debug(0, "pdu->esm_class == %i", deliver_sm->esm_class);
        debug(0, "pdu->protocol_id == %i", deliver_sm->protocol_id);
        debug(0, "pdu->priority_flag == %i", deliver_sm->priority_flag);
        
        debug(0, "pdu->schedule_delivery_time == %s", deliver_sm->schedule_delivery_time);
        debug(0, "pdu->validity_period == %s", deliver_sm->validity_period);
 
        debug(0, "pdu->registered_delivery_flag == %i", deliver_sm->registered_delivery_flag);
        debug(0, "pdu->replace_if_present_flag == %i", deliver_sm->replace_if_present_flag);
        debug(0, "pdu->data_coding == %i", deliver_sm->data_coding);
        debug(0, "pdu->sm_default_msg_id == %i", deliver_sm->sm_default_msg_id);
        debug(0, "pdu->sm_length == %i", deliver_sm->sm_length);
 
        start = malloc( 4 );
        end = malloc( (deliver_sm->sm_length*3) + 1 );
        if(start == NULL) goto error;
        if(end == NULL) goto error;
        memset(end, 0, (deliver_sm->sm_length*3) + 1);
        for(oct=0; oct <>sm_length; oct++) {
               sprintf(start, "%02x ", (unsigned char) deliver_sm->short_message[oct]);
               strcat(end, start);
        }
        debug(0, "pdu->short_message == %s", end);
 
        free(start);
        free(end);     
 
        return 1;
 
error:
        return -1;
}
 
/******************************************************************************
* PDUs
*  QUERY_SM, QUERY_SM_RESP
*/
static int pdu_act_query_sm_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        /* Ignore, this version doesn't send messages which
           get these responses. */
 
        return -1;
}
 
#if 0
static int pdu_act_query_last_msgs_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        /* Ignore, this version doesn't send messages which
           get these responses. */
 
        return -1;
}
        
static int pdu_act_query_msg_details_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        /* Ignore, this version doesn't send messages which
           get these responses. */
 
        return -1;
}
#endif
 
static int pdu_act_cancel_sm_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        /* Ignore, this version doesn't send messages which
           get these responses. */
 
        return -1;
}
 
static int pdu_act_replace_sm_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        /* Ignore, this version doesn't send messages which
           get these responses. */
 
        return -1;
}
 
static int pdu_act_enquire_link(SMSCenter *smsc, smpp_pdu *pdu) {
 
        struct smpp_pdu *newpdu = NULL;
 
        /* Push a ENQUIRE_LINK_RESP on the appropriate fifostack. */
        newpdu = pdu_new();
        if(newpdu==NULL) goto error;
        memset(newpdu, 0, sizeof(struct smpp_pdu));
 
        newpdu->message_body = NULL;
        newpdu->length = 16;
        newpdu->id = SMPP_ENQUIRE_LINK_RESP;
        newpdu->status = 0;
 
        if(pdu->fd == smsc->fd_t) {
               newpdu->sequence_no = smsc->seq_t++;
               fifo_push(smsc->fifo_t_out, newpdu);
        } else if(pdu->fd == smsc->fd_r) {
               newpdu->sequence_no = smsc->seq_r++;
               fifo_push(smsc->fifo_r_out, newpdu);
        }
 
        return 1;
 
error:
        return -1;
}
 
static int pdu_act_enquire_link_resp(SMSCenter *smsc, smpp_pdu *pdu) {
 
        /* Reset the status flag CAN_SEND or CAN_RECEIVE  */
 
        return 1;
}
 
static int pdu_act_generic_nak(SMSCenter *smsc, smpp_pdu *pdu) {
 
        error(0, "pdu_act_generic_nak: SOMETHING IS DREADFULLY WRONG");
 
        debug(0, "pdu->length == %08x", pdu->length);
        debug(0, "pdu->id == %08x", pdu->id);
        debug(0, "pdu->status == %08x", pdu->status);
        debug(0, "pdu->sequence_no == %08x", pdu->sequence_no);
 
        /* Panic  */
 
        return -1;
}
 
static int charset_smpp_to_iso(char* data) {
 
        int i;
 
        while(*data != '\0') {
               i = 0;
               while( translation_table[i].iso != 0 ) {
                       if( translation_table[i].smpp == *data ) {
                               *data = translation_table[i].iso;
                               break;
                       }
                       i++;
               }
               data++;
        }
 
        return 1;
}
 
static int charset_iso_to_smpp(char* data) {
 
        int i;
 
        while(*data != '\0') {
               i = 0;
               while( translation_table[i].iso != 0 ) {
                       if( translation_table[i].iso == *data ) {
                               *data = translation_table[i].smpp;
                               break;
                       }
                       i++;
               }
               data++;
        }
 
        return 1;
}

0 comments

Post a Comment