libsms_putsms.c

Go to the documentation of this file.
00001 /*
00002 SMS Server Tools
00003 Copyright (C) 2000-2002 Stefan Frings
00004 
00005 This program is free software unless you got it under another license directly
00006 from the author. You can redistribute it and/or modify it under the terms of
00007 the GNU General Public License as published by the Free Software Foundation.
00008 Either version 2 of the License, or (at your option) any later version.
00009 
00010 http://www.isis.de/members/~s.frings
00011 mailto:s.frings@mail.isis.de
00012  */
00013 
00014 
00015 #include <sys/types.h>
00016 #include <sys/stat.h>
00017 #include <fcntl.h>
00018 #include <termios.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <unistd.h>
00022 #include <syslog.h>
00023 #include "sms_funcs.h"
00024 #include "libsms_charset.h"
00025 #include "libsms_modem.h"
00026 
00027 
00028 int  sms_report_type;
00029 
00030 static char hexa[16] = {
00031    '0','1','2','3','4','5','6','7',
00032    '8','9','A','B','C','D','E','F'
00033    };
00034 
00035 
00036 void swapchars(char* string, int len) /* Swaps every second character */
00037 {
00038    int position;
00039    char c;
00040 
00041    for (position=0; position<len-1; position+=2)
00042    {
00043       c=string[position];
00044       string[position]=string[position+1];
00045       string[position+1]=c;
00046    }
00047 }
00048 
00049 
00050 
00051 
00052 /* Work with the complex bit building to generate a 7 bit PDU string
00053    encapsulated in 8 bit */
00054 int ascii2pdu(char* ascii, int asciiLength, char* pdu, int cs_convert)
00055 {
00056    static char tmp[500];
00057    int pdubitposition=0;
00058    int pdubyteposition=0;
00059    int character;
00060    int bit;
00061    int pdubitnr;
00062    char converted;
00063    unsigned char foo;
00064 
00065    memset(tmp,0,asciiLength);
00066    for (character=0;character<asciiLength;character++)
00067    {
00068       if (cs_convert)
00069          converted=ascii2sms(ascii[character]);
00070       else
00071          converted=ascii[character];
00072       for (bit=0;bit<7;bit++)
00073       {
00074          pdubitnr=7*character+bit;
00075          pdubyteposition=pdubitnr/8;
00076          pdubitposition=pdubitnr%8;
00077          if (converted & (1<<bit))
00078             tmp[pdubyteposition]=tmp[pdubyteposition]|(1<<pdubitposition);
00079          else
00080             tmp[pdubyteposition]=tmp[pdubyteposition]&~(1<<pdubitposition);
00081       }
00082    }
00083    tmp[pdubyteposition+1]=0;
00084    for (character=0;character<=pdubyteposition; character++)
00085    {
00086       foo = tmp[character] ;
00087       pdu[2*character  ] = hexa[foo>>4];
00088       pdu[2*character+1] = hexa[foo&0x0f];
00089    }
00090    pdu[2*(pdubyteposition+1)]=0;
00091    return 2*(pdubyteposition+1);
00092 }
00093 
00094 
00095 
00096 
00097 /* Create a HEX Dump */
00098 int binary2pdu(char* binary, int length, char* pdu)
00099 {
00100    int character;
00101    unsigned char foo;
00102 
00103    for (character=0;character<length; character++)
00104    {
00105       foo = binary[character];
00106       pdu[2*character  ] = hexa[foo>>4];
00107       pdu[2*character+1] = hexa[foo&0x0f];
00108    }
00109    pdu[2*length]=0;
00110    return 2*length;
00111 }
00112 
00113 
00114 
00115 
00116 /* make the PDU string. The destination variable pdu has to be big enough. */
00117 int make_pdu(struct sms_msg *msg, struct modem *mdm, char* pdu)
00118 {
00119    int  coding;
00120    int  flags;
00121    char tmp[500];
00122    int  pdu_len=0;
00123    int  foo;
00124 
00125    memcpy(tmp,msg->to.s,msg->to.len);
00126    foo = msg->to.len;
00127    tmp[foo] = 0;
00128    // terminate the number with F if the length is odd
00129    if ( foo%2 ) {
00130       tmp[foo]='F';
00131       tmp[++foo] = 0;
00132    }
00133    // Swap every second character
00134    swapchars(tmp,foo);
00135    flags = 0x01;   /* SMS-Submit MS to SMSC */
00136    if (sms_report_type!=NO_REPORT)
00137       flags |= 0x20 ; /* status report request */
00138    coding=240+1; // Dummy + Class 1
00139    if (mdm->mode!=MODE_OLD)
00140       flags+=16; // Validity field
00141    /* concatenate the first part of the PDU string */
00142    if (mdm->mode==MODE_OLD)
00143       pdu_len += sprintf(pdu,"%02X00%02X91%s00%02X%02X",flags,
00144          msg->to.len,tmp,coding,msg->text.len);
00145    else
00146       pdu_len += sprintf(pdu,"00%02X00%02X91%s00%02XA7%02X",flags,
00147          msg->to.len,tmp,coding,msg->text.len);
00148    /* Create the PDU string of the message */
00149    /* pdu_len += binary2pdu(msg->text.s,msg->text.len,pdu+pdu_len); */
00150    pdu_len += ascii2pdu(msg->text.s,msg->text.len,pdu+pdu_len,1/*convert*/);
00151    /* concatenate the text to the PDU string */
00152    return pdu_len;
00153 }
00154 
00155 
00156 
00157 
00158 /* search into modem reply for the sms id */
00159 inline int fetch_sms_id(char *answer)
00160 {
00161    char *p;
00162    int  id;
00163 
00164    p = strstr(answer,"+CMGS:");
00165    if (!p)
00166       goto error;
00167    p += 6;
00168    /* parse to the first digit */
00169    while(p && *p && (*p==' ' || *p=='\r' || *p=='\n'))
00170       p++;
00171    if (*p<'0' || *p>'9')
00172       goto error;
00173    /* convert the number*/
00174    id = 0;
00175    while (p && *p>='0' && *p<='9')
00176       id = id*10 + *(p++)-'0';
00177 
00178    return id;
00179 error:
00180    return -1;
00181 }
00182 
00183 
00184 
00185 
00186 /* send sms */
00187 int putsms( struct sms_msg *sms_messg, struct modem *mdm)
00188 {
00189    char command[500];
00190    char command2[500];
00191    char answer[500];
00192    char pdu[500];
00193    int clen,clen2;
00194    int retries;
00195    int err_code;
00196    int pdu_len;
00197    int sms_id;
00198 
00199    pdu_len = make_pdu(sms_messg, mdm, pdu);
00200    if (mdm->mode==MODE_OLD)
00201       clen = sprintf(command,"AT+CMGS=%i\r",pdu_len/2);
00202    else if (mdm->mode==MODE_ASCII)
00203       clen = sprintf(command,"AT+CMGS=\"+%.*s\"\r",sms_messg->to.len,
00204          sms_messg->to.s);
00205    else
00206       clen = sprintf(command,"AT+CMGS=%i\r",pdu_len/2-1);
00207 
00208    if (mdm->mode==MODE_ASCII)
00209       clen2=sprintf(command2,"%.*s\x1A",sms_messg->text.len,
00210       sms_messg->text.s);
00211    else
00212       clen2=sprintf(command2,"%.*s\x1A",pdu_len,pdu);
00213 
00214    sms_id = 0;
00215    for(err_code=0,retries=0;err_code<2 && retries<mdm->retry; retries++)
00216    {
00217       if (put_command(mdm,command,clen,answer,sizeof(answer),50,"\r\n> ")
00218       && put_command(mdm,command2,clen2,answer,sizeof(answer),1000,0)
00219       && strstr(answer,"OK") )
00220       {
00221          /* no error during sending and the modem said OK */
00222          err_code = 2;
00223          /* if reports were request, we have to fetch the sms id from
00224          the modem reply to keep trace of the status reports */
00225          if (sms_report_type!=NO_REPORT) {
00226             sms_id = fetch_sms_id(answer);
00227             if (sms_id==-1)
00228                err_code = 1;
00229          }
00230       } else {
00231          /* we have an error */
00232          if (checkmodem(mdm)==-1) {
00233             err_code = 0;
00234             LM_WARN("resending last sms! \n");
00235          } else if (err_code==0) {
00236             LM_WARN("possible corrupted sms. Let's try again!\n");
00237             err_code = 1;
00238          }else {
00239             LM_ERR("We have a FUBAR sms!! drop it!\n");
00240             err_code = 3;
00241          }
00242       }
00243    }
00244 
00245    if (err_code==0)
00246       LM_WARN("something spooky is going on with the modem!"
00247          " Re-inited and re-tried for %d times without success!\n",
00248          mdm->retry);
00249    return (err_code==0?-2:(err_code==2?sms_id:-1));
00250 }
00251 

Generated on Wed May 23 18:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6