- Use time_t instead of abstract minutes to store validity time to make sure we support all possible values. - Return UNIX time from it to support both relative and absolute expire times. - Pass a current time to gsm340_validity_period() to compute the absolute expire time if a relative time is specified. What time is "current" is to b - We also introduce SMS_DEFAULT_VALIDITY_PERIOD macros to reduce number of magic values.
PS This is a first patch of a series of patches which fix SMS validity time decoding. I'm cleaning the patch set and want to see if this patch is fine, as other patches rely on it.
Hi Daniel, Holger,
Have you had any luck reviewing this patchset (achemeris/sms-validity branch in git)?
On Fri, Mar 7, 2014 at 8:11 PM, Alexander Chemeris alexander.chemeris@gmail.com wrote:
- Use time_t instead of abstract minutes to store validity time to make sure
we support all possible values.
- Return UNIX time from it to support both relative and absolute expire
times.
- Pass a current time to gsm340_validity_period() to compute the absolute
expire time if a relative time is specified. What time is "current" is to b
- We also introduce SMS_DEFAULT_VALIDITY_PERIOD macros to reduce number of
magic values.
PS This is a first patch of a series of patches which fix SMS validity time decoding. I'm cleaning the patch set and want to see if this patch is fine, as other patches rely on it.
-- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. / ООО УмРадио https://fairwaves.co
Hello,
a few comments inline.
On Fri, 2014-03-07 at 20:11, Alexander Chemeris wrote:
PS This is a first patch of a series of patches which fix SMS validity time decoding. I'm cleaning the patch set and want to see if this patch is fine, as other patches rely on it.
From 840b7ca3efa834a0d02e4e32f62d3dac63c6bac6 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Alexander.Chemeris@gmail.com Date: Tue, 26 Nov 2013 16:43:10 -0600 Subject: [PATCH] sms: Proper decoding and storage of SMS validity period.
- Use time_t instead of abstract minutes to store validity time to make sure we support all possible values.
- Return UNIX time from it to support both relative and absolute expire times.
- Pass a current time to gsm340_validity_period() to compute the absolute expire time if a relative time is specified. What time is "current" is to be decided by callers.
- We also introduce SMS_DEFAULT_VALIDITY_PERIOD macros to reduce number of magic values.
include/osmocom/gsm/gsm0411_utils.h | 7 ++-- src/gsm/gsm0411_utils.c | 62 +++++++++++++++-------------------- 2 files changed, 31 insertions(+), 38 deletions(-)
diff --git a/include/osmocom/gsm/gsm0411_utils.h b/include/osmocom/gsm/gsm0411_utils.h index ad368e6..cad3625 100644 --- a/include/osmocom/gsm/gsm0411_utils.h +++ b/include/osmocom/gsm/gsm0411_utils.h @@ -3,6 +3,9 @@
#include <time.h>
+/* Default SMS validity period is 2 days */ +#define SMS_DEFAULT_VALIDITY_PERIOD (2 * 24 * 60 * 60)
/* Turn int into semi-octet representation: 98 => 0x89 */ uint8_t gsm411_bcdify(uint8_t value);
@@ -17,8 +20,8 @@ void gsm340_gen_scts(uint8_t *scts, time_t time); /* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */ time_t gsm340_scts(uint8_t *scts);
-/* decode validity period. return minutes */ -unsigned long gsm340_validity_period(uint8_t sms_vpf, uint8_t *sms_vp); +/* decode validity period. return absolute time */ +time_t gsm340_validity_period(time_t now, uint8_t sms_vpf, uint8_t *sms_vp);
/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */ enum sms_alphabet gsm338_get_sms_alphabet(uint8_t dcs); diff --git a/src/gsm/gsm0411_utils.c b/src/gsm/gsm0411_utils.c index a8ba810..1a6862b 100644 --- a/src/gsm/gsm0411_utils.c +++ b/src/gsm/gsm0411_utils.c @@ -34,6 +34,7 @@
#include <osmocom/gsm/gsm48.h> #include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/gsm0411_utils.h> #include <osmocom/gsm/protocol/gsm_03_40.h> #include <osmocom/gsm/protocol/gsm_04_11.h>
@@ -121,16 +122,14 @@ time_t gsm340_scts(uint8_t *scts) }
/* Return the default validity period in minutes */
You need to update the comment.
-static unsigned long gsm340_vp_default(void) +static time_t gsm340_vp_default(time_t now) {
- unsigned long minutes; /* Default validity: two days */
- minutes = 24 * 60 * 2;
- return minutes;
- return now + SMS_DEFAULT_VALIDITY_PERIOD;
}
/* Decode validity period format 'relative' */ -static unsigned long gsm340_vp_relative(uint8_t *sms_vp) +static unsigned long gsm340_vp_relative(time_t now, uint8_t *sms_vp)
You should probably return time_t here as well. Also the variable minutes should become time_t as well.
{ /* Chapter 9.2.3.12.1 */ uint8_t vp; @@ -145,58 +144,49 @@ static unsigned long gsm340_vp_relative(uint8_t *sms_vp) minutes = vp-166 * 60 * 24; else minutes = vp-192 * 60 * 24 * 7;
- return minutes;
- /* Calculate absolute time from the relative offset */
- return now + minutes * 60;
}
/* Decode validity period format 'absolute' */ -static unsigned long gsm340_vp_absolute(uint8_t *sms_vp) +static time_t gsm340_vp_absolute(uint8_t *sms_vp) { /* Chapter 9.2.3.12.2 */
- time_t expires, now;
- unsigned long minutes;
- expires = gsm340_scts(sms_vp);
- now = time(NULL);
- if (expires <= now)
minutes = 0;- else
minutes = (expires-now)/60;- return minutes;
- return gsm340_scts(sms_vp);
}
/* Decode validity period format 'relative in integer representation' */ -static unsigned long gsm340_vp_relative_integer(uint8_t *sms_vp) +static time_t gsm340_vp_relative_integer(time_t now, uint8_t *sms_vp) { uint8_t vp;
- unsigned long minutes; vp = *(sms_vp); if (vp == 0) { LOGP(DLSMS, LOGL_ERROR, "reserved relative_integer validity period\n");
return gsm340_vp_default();
return gsm340_vp_default(now);
Please add a comment (with FIXME) or #warning that we should return an RP-Error here.
}
- minutes = vp/60;
- return minutes;
- return now + vp;
}
/* Decode validity period format 'relative in semi-octet representation' */ -static unsigned long gsm340_vp_relative_semioctet(uint8_t *sms_vp) +static time_t gsm340_vp_relative_semioctet(time_t now, uint8_t *sms_vp) {
- unsigned long minutes;
- minutes = gsm411_unbcdify(*sms_vp++)*60; /* hours */
- minutes += gsm411_unbcdify(*sms_vp++); /* minutes */
- minutes += gsm411_unbcdify(*sms_vp++)/60; /* seconds */
- return minutes;
- unsigned long hours, minutes, seconds;
time_t?
- hours = gsm411_unbcdify(*sms_vp++); /* hours */
- minutes = gsm411_unbcdify(*sms_vp++); /* minutes */
- seconds = gsm411_unbcdify(*sms_vp++); /* seconds */
- return now + hours*60*60 + minutes*60 + seconds;
}
/* decode validity period. return minutes */
The comment is wrong now
-unsigned long gsm340_validity_period(uint8_t sms_vpf, uint8_t *sms_vp) +time_t gsm340_validity_period(time_t now, uint8_t sms_vpf, uint8_t *sms_vp) { uint8_t fi; /* functionality indicator */
switch (sms_vpf) { case GSM340_TP_VPF_RELATIVE:
return gsm340_vp_relative(sms_vp);
return gsm340_vp_relative(now, sms_vp);
You could also omit now in all the static function and return now + func() in gsm340_validity_period(). That looks slightly cleaner to me and shouldn't change testability.
case GSM340_TP_VPF_ABSOLUTE: return gsm340_vp_absolute(sms_vp); case GSM340_TP_VPF_ENHANCED: @@ -207,23 +197,23 @@ unsigned long gsm340_validity_period(uint8_t sms_vpf, uint8_t *sms_vp) /* read validity period format */ switch (fi & 0x7) { case 0x0:
return gsm340_vp_default(); /* no vpf specified */
case 0x1:return gsm340_vp_default(now); /* no vpf specified */
return gsm340_vp_relative(sms_vp);
case 0x2:return gsm340_vp_relative(now, sms_vp);
return gsm340_vp_relative_integer(sms_vp);
case 0x3:return gsm340_vp_relative_integer(now, sms_vp);
return gsm340_vp_relative_semioctet(sms_vp);
default: /* The GSM spec says that the SC should reject any unsupported and/or undefined values. FIXME */ LOGP(DLSMS, LOGL_ERROR, "Reserved enhanced validity period format\n");return gsm340_vp_relative_semioctet(now, sms_vp);
return gsm340_vp_default();
} case GSM340_TP_VPF_NONE: default:return gsm340_vp_default(now);
return gsm340_vp_default();
}return gsm340_vp_default(now);}
-- 1.7.9.5
Regards, Daniel
Hi Daniel,
On Tue, Mar 11, 2014 at 11:26 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
On Fri, 2014-03-07 at 20:11, Alexander Chemeris wrote:
-unsigned long gsm340_validity_period(uint8_t sms_vpf, uint8_t *sms_vp) +time_t gsm340_validity_period(time_t now, uint8_t sms_vpf, uint8_t *sms_vp) { uint8_t fi; /* functionality indicator */
switch (sms_vpf) { case GSM340_TP_VPF_RELATIVE:
return gsm340_vp_relative(sms_vp);
return gsm340_vp_relative(now, sms_vp);You could also omit now in all the static function and return now + func() in gsm340_validity_period(). That looks slightly cleaner to me and shouldn't change testability.
I made it this way to follow a principle of least surprise - you know, that you always get absolute time as a return value and you don't even need to think about this. But that said, this is a minor issue to me, so I've changed it.
All other comments are proper and are also fixed in the attached patch and in the branch (achemeris/sms-validity).
I've updated the patch to rename gsm340_validity_period() to gsm340_validity_period_2() and keep gsm340_validity_period() as a deprecated broken implementation. This way we keep compatibility with older OpenBSC versions without updating to a new libosmocore library.
Branch achemeris/sms-validity is updated accordingly.
Hello Alexander,
On Wed, 2014-03-12 at 01:44, Alexander Chemeris wrote:
I've updated the patch to rename gsm340_validity_period() to gsm340_validity_period_2() and keep gsm340_validity_period() as a deprecated broken implementation. This way we keep compatibility with older OpenBSC versions without updating to a new libosmocore library.
looks all fine except for the function name. Something more expressive would be nice - how about gsm340_validity_period_as_ts()?
Regards, Daniel
On Wed, Mar 12, 2014 at 6:59 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
Hello Alexander,
On Wed, 2014-03-12 at 01:44, Alexander Chemeris wrote:
I've updated the patch to rename gsm340_validity_period() to gsm340_validity_period_2() and keep gsm340_validity_period() as a deprecated broken implementation. This way we keep compatibility with older OpenBSC versions without updating to a new libosmocore library.
looks all fine except for the function name. Something more expressive would be nice - how about gsm340_validity_period_as_ts()?
I'm not sure "as_ts" is really more expressive, gsm340_validity_period_unix_time() would be more expressive, but it's also painfully long. I would suggest: - gsm340_validity_time() - gsm340_validity_period_decode() - leave as is
On Wed, Mar 12, 2014 at 7:53 PM, Alexander Chemeris alexander.chemeris@gmail.com wrote:
On Wed, Mar 12, 2014 at 6:59 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
Hello Alexander,
On Wed, 2014-03-12 at 01:44, Alexander Chemeris wrote:
I've updated the patch to rename gsm340_validity_period() to gsm340_validity_period_2() and keep gsm340_validity_period() as a deprecated broken implementation. This way we keep compatibility with older OpenBSC versions without updating to a new libosmocore library.
looks all fine except for the function name. Something more expressive would be nice - how about gsm340_validity_period_as_ts()?
I'm not sure "as_ts" is really more expressive, gsm340_validity_period_unix_time() would be more expressive, but it's also painfully long. I would suggest:
- gsm340_validity_time()
- gsm340_validity_period_decode()
- leave as is
- gsm340_valid_until()
On Wed, 2014-03-12 at 19:53, Alexander Chemeris wrote:
On Wed, Mar 12, 2014 at 6:59 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
looks all fine except for the function name. Something more expressive would be nice - how about gsm340_validity_period_as_ts()?
I'm not sure "as_ts" is really more expressive,
gsm340_validity_period_unix_time() would be more expressive, but it's also painfully long. I would suggest:
- gsm340_validity_time()
I like that one.
Regards,
On Wed, Mar 12, 2014 at 8:02 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
On Wed, 2014-03-12 at 19:53, Alexander Chemeris wrote:
On Wed, Mar 12, 2014 at 6:59 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
looks all fine except for the function name. Something more expressive would be nice - how about gsm340_validity_period_as_ts()?
I'm not sure "as_ts" is really more expressive,
gsm340_validity_period_unix_time() would be more expressive, but it's also painfully long. I would suggest:
- gsm340_validity_time()
I like that one.
Updated
Hi Holger,
it seems there are no more comments on this code. Could you please merge it? It is independent of other changes.
On Wed, Mar 12, 2014 at 9:06 PM, Alexander Chemeris alexander.chemeris@gmail.com wrote:
On Wed, Mar 12, 2014 at 8:02 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
On Wed, 2014-03-12 at 19:53, Alexander Chemeris wrote:
On Wed, Mar 12, 2014 at 6:59 PM, Daniel Willmann dwillmann@sysmocom.de wrote:
looks all fine except for the function name. Something more expressive would be nice - how about gsm340_validity_period_as_ts()?
I'm not sure "as_ts" is really more expressive,
gsm340_validity_period_unix_time() would be more expressive, but it's also painfully long. I would suggest:
- gsm340_validity_time()
I like that one.
Updated
-- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. / ООО УмРадио https://fairwaves.co
On Sun, Mar 16, 2014 at 01:40:58PM +0400, Alexander Chemeris wrote:
Dear Alexander,
it seems there are no more comments on this code. Could you please merge it? It is independent of other changes.
there is a fixed amount of time I can spend on review a week. You sadly have used some of this time by sending not compiling patches, wrong ones, etc. This means you will need to wait for my next timeslot.
The lack of comments doesn't mean that there will be none. E.g. in one of the testcases I noticed that you don't use C99 initializers but the old/error prone way of initializing. :)
holger
PS: I will not reply the same to all your other messages. ;)
On Wed, Mar 12, 2014 at 09:06:29PM +0400, Alexander Chemeris wrote:
+/* Decode validity period format 'relative in integer representation'.
- Returns number of seconds relative to a current time. */
this style of comments is only for net/* in the kernel coding style.
+static time_t gsm340_vp_relative_integer(uint8_t *sms_vp) { uint8_t vp;
- unsigned long minutes; vp = *(sms_vp); if (vp == 0) { LOGP(DLSMS, LOGL_ERROR, "reserved relative_integer validity period\n");
return gsm340_vp_default();+#warning We should return an RP-Error here.
return SMS_DEFAULT_VALIDITY_PERIOD;
What does this warning mean? The code will not be able to generate and initiate the RP-Error procedure. So how do you intend to indicate the error condition? What should the caler do?
Hi Holger,
On Thu, 2014-03-20 at 22:20, Holger Hans Peter Freyther wrote:
On Wed, Mar 12, 2014 at 09:06:29PM +0400, Alexander Chemeris wrote:
+static time_t gsm340_vp_relative_integer(uint8_t *sms_vp) { uint8_t vp;
- unsigned long minutes; vp = *(sms_vp); if (vp == 0) { LOGP(DLSMS, LOGL_ERROR, "reserved relative_integer validity period\n");
return gsm340_vp_default();+#warning We should return an RP-Error here.
return SMS_DEFAULT_VALIDITY_PERIOD;What does this warning mean? The code will not be able to generate and initiate the RP-Error procedure. So how do you intend to indicate the error condition? What should the caler do?
The GSM spec wants us to send back an RP-Error in this case as well as in the default: of gsm340_validity_period(). The latter already has a FIXME comment in it and I just wanted to make sure we don't forget this case if we implement the rp-error. That's why I asked that we either put a FIXME or #warning here.
I think we can signal an error condition by returning 0 (both in gsm340_vp_relative_integer() and in gsm340_validity_time() and the caller of gsm340_validity_time() can then deal with the error and return a proper RP-Error in the future.
Thinking about it I guess we should implement it like that right now.
Regards, Daniel