An example SMS Server component

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  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 = '';

 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 != '') {

 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 != '') {

 i = 0;

 while( translation_table[i].iso != 0 ) {

 if( translation_table[i].iso == *data ) {

 *data = translation_table[i].smpp;

 break;

 }

 i++;

 }

 data++;

 }

 return 1;

}

Advertisements

One Comment Add yours

  1. Kannah says:

    Nice Upload.. Thanks a lot… \m/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s