Probably more accurate when parsing messages in PDU mode
This commit is contained in:
parent
fbecdf8628
commit
37cfa0d3fb
98
src/gsm.c
98
src/gsm.c
@ -1417,10 +1417,14 @@ static int _gsm_trigger_cmgl(GSM * gsm, char const * result)
|
|||||||
|
|
||||||
/* gsm_trigger_cmgr */
|
/* gsm_trigger_cmgr */
|
||||||
static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
||||||
char number[32]);
|
char number[32], GSMEncoding * encoding);
|
||||||
static void _cmgr_pdu_parse_number(char const * number, size_t length,
|
static void _cmgr_pdu_parse_number(char const * number, size_t length,
|
||||||
char buf[32]);
|
char buf[32]);
|
||||||
static time_t _cmgr_pdu_parse_timestamp(char const * timestamp);
|
static time_t _cmgr_pdu_parse_timestamp(char const * timestamp);
|
||||||
|
static char * _cmgr_pdu_parse_encoding_default(char const * pdu, size_t len,
|
||||||
|
size_t i, size_t hdr, GSMEncoding * encoding);
|
||||||
|
static char * _cmgr_pdu_parse_encoding_data(char const * pdu, size_t len,
|
||||||
|
size_t i, size_t hdr, GSMEncoding * encoding);
|
||||||
|
|
||||||
static int _gsm_trigger_cmgr(GSM * gsm, char const * result)
|
static int _gsm_trigger_cmgr(GSM * gsm, char const * result)
|
||||||
{
|
{
|
||||||
@ -1465,7 +1469,8 @@ static int _gsm_trigger_cmgr(GSM * gsm, char const * result)
|
|||||||
_gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE);
|
_gsm_event_send(gsm, GSM_EVENT_TYPE_MESSAGE);
|
||||||
}
|
}
|
||||||
else if((p = _cmgr_pdu_parse(result, &gsm->event.message.date,
|
else if((p = _cmgr_pdu_parse(result, &gsm->event.message.date,
|
||||||
gsm->number)) != NULL)
|
gsm->number,
|
||||||
|
&gsm->event.message.encoding)) != NULL)
|
||||||
{
|
{
|
||||||
gsm->event.message.index = 0;
|
gsm->event.message.index = 0;
|
||||||
if((gsmc = g_slist_nth_data(gsm->queue, 0)) != NULL)
|
if((gsmc = g_slist_nth_data(gsm->queue, 0)) != NULL)
|
||||||
@ -1489,22 +1494,19 @@ static int _gsm_trigger_cmgr(GSM * gsm, char const * result)
|
|||||||
|
|
||||||
/* XXX this function is fat and ugly */
|
/* XXX this function is fat and ugly */
|
||||||
static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
||||||
char number[32])
|
char number[32], GSMEncoding * encoding)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned int smscl;
|
unsigned int smscl;
|
||||||
|
unsigned int tp;
|
||||||
|
unsigned int hdr;
|
||||||
unsigned int addrl;
|
unsigned int addrl;
|
||||||
unsigned int pid;
|
unsigned int pid;
|
||||||
unsigned int dcs;
|
unsigned int dcs;
|
||||||
unsigned int datal;
|
unsigned int datal;
|
||||||
unsigned int u;
|
unsigned int u;
|
||||||
unsigned char * p;
|
|
||||||
char const * q;
|
char const * q;
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t j;
|
|
||||||
unsigned char byte;
|
|
||||||
unsigned char rest;
|
|
||||||
int shift;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, pdu);
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, pdu);
|
||||||
@ -1515,10 +1517,11 @@ static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
|||||||
if((smscl * 2) + 2 > len)
|
if((smscl * 2) + 2 > len)
|
||||||
return NULL;
|
return NULL;
|
||||||
q = pdu + (smscl * 2) + 2;
|
q = pdu + (smscl * 2) + 2;
|
||||||
if(sscanf(q, "%02X", &u) != 1)
|
if(sscanf(q, "%02X", &tp) != 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
if((u & 0x04) != 0x04) /* SMS-DELIVER */
|
if((tp & 0x03) != 0x00) /* TP-MTI not SMS-DELIVER */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
hdr = ((tp & 0x40) == 0x40) ? 1 : 0; /* TP-UDHI header present */
|
||||||
if((smscl * 2) + 4 > len)
|
if((smscl * 2) + 4 > len)
|
||||||
return NULL;
|
return NULL;
|
||||||
q = pdu + (smscl * 2) + 4;
|
q = pdu + (smscl * 2) + 4;
|
||||||
@ -1543,7 +1546,6 @@ static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
|||||||
q = pdu + (smscl * 2) + 2 + 4 + addrl + 4;
|
q = pdu + (smscl * 2) + 2 + 4 + addrl + 4;
|
||||||
if(sscanf(q, "%02X", &dcs) != 1) /* DCS */
|
if(sscanf(q, "%02X", &dcs) != 1) /* DCS */
|
||||||
return NULL;
|
return NULL;
|
||||||
/* FIXME check the DCS */
|
|
||||||
if((smscl * 2) + 2 + 4 + addrl + 6 > len)
|
if((smscl * 2) + 2 + 4 + addrl + 6 > len)
|
||||||
return NULL;
|
return NULL;
|
||||||
q = pdu + (smscl * 2) + 2 + 4 + addrl + 6;
|
q = pdu + (smscl * 2) + 2 + 4 + addrl + 6;
|
||||||
@ -1555,18 +1557,46 @@ static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
|||||||
if(sscanf(q, "%02X", &datal) != 1) /* data length */
|
if(sscanf(q, "%02X", &datal) != 1) /* data length */
|
||||||
return NULL;
|
return NULL;
|
||||||
/* XXX check the data length */
|
/* XXX check the data length */
|
||||||
if((smscl * 2) + 2 + 4 + addrl + 6 + 16 > len)
|
if((i = (smscl * 2) + 2 + 4 + addrl + 6 + 16) > len)
|
||||||
return NULL;
|
return NULL;
|
||||||
q = pdu + (smscl * 2) + 2 + 4 + addrl + 6 + 16;
|
if(hdr != 0 && sscanf(&pdu[i], "%02X", &hdr) != 1)
|
||||||
i = (smscl * 2) + 2 + 4 + addrl + 6 + 16;
|
return NULL;
|
||||||
|
if(dcs == 0x00)
|
||||||
|
return _cmgr_pdu_parse_encoding_default(pdu, len, i, hdr,
|
||||||
|
encoding);
|
||||||
|
if(dcs == 0x04)
|
||||||
|
return _cmgr_pdu_parse_encoding_data(pdu, len, i, hdr,
|
||||||
|
encoding);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * _cmgr_pdu_parse_encoding_default(char const * pdu, size_t len,
|
||||||
|
size_t i, size_t hdr, GSMEncoding * encoding)
|
||||||
|
{
|
||||||
|
unsigned char * p;
|
||||||
|
size_t j;
|
||||||
|
unsigned char rest;
|
||||||
|
int shift = 0;
|
||||||
|
char const * q;
|
||||||
|
unsigned int u;
|
||||||
|
unsigned char byte;
|
||||||
|
|
||||||
if((p = malloc((len - i) * 2)) == NULL)
|
if((p = malloc((len - i) * 2)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if(hdr != 0)
|
||||||
|
{
|
||||||
|
/* FIXME actually parse the header */
|
||||||
|
u = 2 + (hdr * 2);
|
||||||
|
if(u % 7 != 0) /* fill bits */
|
||||||
|
u += 7 - (u % 7);
|
||||||
|
i += u;
|
||||||
|
}
|
||||||
p[0] = '\0';
|
p[0] = '\0';
|
||||||
for(j = 0, rest = 0, shift = 0; i + 1 < len; i+=2)
|
for(j = 0, rest = 0; i + 1 < len; i+=2)
|
||||||
{
|
{
|
||||||
q = &pdu[i];
|
q = &pdu[i];
|
||||||
if(sscanf(q, "%02X", &u) != 1)
|
if(sscanf(q, "%02X", &u) != 1)
|
||||||
break;
|
break; /* FIXME report an error instead? */
|
||||||
byte = u;
|
byte = u;
|
||||||
p[j] = (byte << (shift + 1) >> (shift + 1) << shift) & 0x7f;
|
p[j] = (byte << (shift + 1) >> (shift + 1) << shift) & 0x7f;
|
||||||
p[j] |= rest;
|
p[j] |= rest;
|
||||||
@ -1581,6 +1611,31 @@ static char * _cmgr_pdu_parse(char const * pdu, time_t * timestamp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p[j] = '\0';
|
p[j] = '\0';
|
||||||
|
*encoding = GSM_ENCODING_UTF8;
|
||||||
|
return (char *)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * _cmgr_pdu_parse_encoding_data(char const * pdu, size_t len,
|
||||||
|
size_t i, size_t hdr, GSMEncoding * encoding)
|
||||||
|
{
|
||||||
|
unsigned char * p;
|
||||||
|
size_t j;
|
||||||
|
unsigned int u;
|
||||||
|
|
||||||
|
if((p = malloc((len - i) * 2)) == NULL) /* XXX 4 times big enough? */
|
||||||
|
return NULL;
|
||||||
|
/* FIXME actually parse the header */
|
||||||
|
i += 2 + (hdr * 2);
|
||||||
|
for(j = 0; i + 1 < len; i+=2)
|
||||||
|
{
|
||||||
|
if(sscanf(&pdu[i], "%02X", &u) != 1)
|
||||||
|
{
|
||||||
|
free(p);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
p[j++] = u;
|
||||||
|
}
|
||||||
|
*encoding = GSM_ENCODING_RAW_DATA;
|
||||||
return (char *)p;
|
return (char *)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1599,6 +1654,10 @@ static void _cmgr_pdu_parse_number(char const * number, size_t length,
|
|||||||
buf[i + 1] = '\0';
|
buf[i + 1] = '\0';
|
||||||
}
|
}
|
||||||
buf[31] = '\0';
|
buf[31] = '\0';
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\", %lu) => \"%s\"\n", __func__, number,
|
||||||
|
length, buf);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t _cmgr_pdu_parse_timestamp(char const * timestamp)
|
static time_t _cmgr_pdu_parse_timestamp(char const * timestamp)
|
||||||
@ -1606,6 +1665,9 @@ static time_t _cmgr_pdu_parse_timestamp(char const * timestamp)
|
|||||||
char const * p = timestamp;
|
char const * p = timestamp;
|
||||||
size_t i;
|
size_t i;
|
||||||
struct tm t;
|
struct tm t;
|
||||||
|
#ifdef DEBUG
|
||||||
|
char buf[32];
|
||||||
|
#endif
|
||||||
|
|
||||||
if(strlen(p) < 14)
|
if(strlen(p) < 14)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1620,6 +1682,10 @@ static time_t _cmgr_pdu_parse_timestamp(char const * timestamp)
|
|||||||
t.tm_hour = (p[6] - '0') + ((p[7] - '0') * 10);
|
t.tm_hour = (p[6] - '0') + ((p[7] - '0') * 10);
|
||||||
t.tm_min = (p[8] - '0') + ((p[9] - '0') * 10);
|
t.tm_min = (p[8] - '0') + ((p[9] - '0') * 10);
|
||||||
t.tm_sec = (p[10] - '0') + ((p[11] - '0') * 10);
|
t.tm_sec = (p[10] - '0') + ((p[11] - '0') * 10);
|
||||||
|
#ifdef DEBUG
|
||||||
|
strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M:%S", &t);
|
||||||
|
fprintf(stderr, "DEBUG: %s() => \"%s\"\n", __func__, buf);
|
||||||
|
#endif
|
||||||
return mktime(&t);
|
return mktime(&t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user