From 9a35914bc1c7b78d13ec400350eb8639e8125a0e Mon Sep 17 00:00:00 2001 From: Dennis Wehrle Date: Tue, 22 Mar 2011 18:25:53 +0100 Subject: [PATCH] SMS-fix: due to a misuse of user_data_len the sms where cropped (on vty) and wrongly stored on the database. Therefore two new functions was created: uint8_t gsm_get_octet_len(const uint8_t sept_len) and uint8_t gsm_get_septet_len(const char *text) --- include/osmocore/gsm_utils.h | 3 ++ src/gsm_utils.c | 54 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/include/osmocore/gsm_utils.h b/include/osmocore/gsm_utils.h index 0aadd2e..a47ce7b 100644 --- a/include/osmocore/gsm_utils.h +++ b/include/osmocore/gsm_utils.h @@ -59,6 +59,9 @@ enum gsm_band gsm_band_parse(const char *mhz); int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length); int gsm_7bit_encode(uint8_t *result, const char *data); +uint8_t gsm_get_octet_len(const uint8_t sept_len); +uint8_t gsm_get_septet_len(const char *text); + int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm); int ms_pwr_dbm(enum gsm_band band, uint8_t lvl); diff --git a/src/gsm_utils.c b/src/gsm_utils.c index 31e3cd6..faac7cf 100644 --- a/src/gsm_utils.c +++ b/src/gsm_utils.c @@ -73,17 +73,52 @@ static int gsm_septet_lookup(uint8_t ch) return -1; } +/* Warning, user_data_len indicates the amount of septets (characters), we need amount of octets occupied */ +/* compute the number of octets: */ +/* #octets = (#septets * 7 bit) / 8 bit */ +/* e.g. 47 non-extension characters needs 329 bits / 8 bit = 41,125 octets => we need 42 octets for 47 characters */ +uint8_t gsm_get_octet_len(const uint8_t sept_len){ + int octet_len = (sept_len * 7) / 8; + if ((sept_len * 7) % 8 != 0) + octet_len++; + + return octet_len; +} + + +/* Get number of septets. Each extension character has to be count twice, because they need 2 septets*/ +uint8_t gsm_get_septet_len(const char *text){ + uint8_t septet_len = strlen(text); + int i; + for(i = 0; i < strlen(text); i++){ + switch(text[i]){ + case 0x0c: + case 0x5e: + case 0x7b: + case 0x7d: + case 0x5c: + case 0x5b: + case 0x7e: + case 0x5d: + case 0x7c: + septet_len++; + default: + continue; + } + } + return septet_len; +} + /* GSM 03.38 6.2.1 Character unpacking */ int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length) { int i = 0; - int l = 0; - int septet_l = (length * 8) / 7; + + int septet_l = length; uint8_t *rtext = calloc(septet_l, sizeof(uint8_t)); uint8_t tmp; /* FIXME: We need to account for user data headers here */ - i += l; for (; i < septet_l; i++){ rtext[i] = ((user_data[(i * 7 + 7) >> 3] << @@ -155,6 +190,12 @@ int gsm_7bit_encode(uint8_t *result, const char *data) shift = 0; continue; } + /* special end case. This is necessary if the last septet fits into the previous octet. */ + /* E.g. 48 non-extension characters: ....ag ( a = 1100001, g = 1100111) */ + /* result[40] = 100001 XX */ + /* result[41] = 1100111 1 */ + if(shift == 7 && i + 1 == y) + break; cb = (rdata[i] & 0x7f) >> shift; if(i + 1 < y){ @@ -168,7 +209,12 @@ int gsm_7bit_encode(uint8_t *result, const char *data) } free(rdata); - return z; + + /* we don't care about the number of octets, because they are not unique. E.g.: */ + /* 1.) 46 non-extension characters + 1 extension character => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets */ + /* 2.) 47 non-extension characters => (47 * 7 bit) / 8 bit = 41,125 = 42 octets */ + /* 3.) 48 non-extension characters => (48 * 7 bit) / 8 bit = 42 octects */ + return y; } /* determine power control level for given dBm value, as indicated -- 1.7.1