pjsua: auto re-registration ignores the retry interval when it is below the jitter #5318
Description
Summary
schedule_reregistration() randomises the registration retry delay by reg_retry_random_interval (10 s by default). When the retry interval is below that value, the code clears delay.sec before using it:
pjproject/pjsip/src/pjsua-lib/pjsua_acc.c
Lines 5524 to 5533 in 9192b71
| /* Randomize interval by +/- reg_retry_random_interval, if configured */ | |
| if (acc->cfg.reg_retry_random_interval) { | |
| long rand_ms = acc->cfg.reg_retry_random_interval * 1000; | |
| if (delay.sec >= (long)acc->cfg.reg_retry_random_interval) { | |
| delay.msec = -rand_ms + (pj_rand() % (rand_ms * 2)); | |
| } else { | |
| delay.sec = 0; | |
| delay.msec = (pj_rand() % (delay.sec * 1000 + rand_ms)); | |
| } | |
| } |
so delay.sec * 1000 is always 0 and the delay is a uniform 0 to reg_retry_random_interval, whatever the interval is. A reg_retry_interval or reg_first_retry_interval of 1 and one of 9 behave alike, and the mean delay is 5 s for every value below 10 but 10 s at 10, so a longer interval can retry sooner on average.
This was pointed out in the review of #5306, which makes it reachable from pjsua through --rereg-delay. It affects any application that sets these fields through the C or pjsua2 API.
History
The 2011 code (#1375) was flat: if (delay.sec >= 10) { ±10 s } else { delay.sec = 0; delay.msec = rand % 10000; }. e9268d2 (#1802) made the 10 configurable and wrote delay.sec * 1000 + rand_ms in the modulo, but cleared delay.sec on the line before, so that term has been 0 ever since. The behaviour is the one the code has had since 2011, not a regression.
Steps to reproduce
With #5306 applied, so that --rereg-delay reaches the account, run pjsua against a TCP registrar port with nothing listening on it:
pjsua --null-audio --no-udp --id sip:test@127.0.0.1 --registrar 'sip:127.0.0.1:5999;transport=tcp' --realm '*' --username test --password test --rereg-delay=9
Expected: retries about 9 s apart, spread by reg_retry_random_interval (0 to 19 s). Actual: retries 0 to 10 s apart, the same as for --rereg-delay=1.
Fix
PR to follow. It computes the delay before clearing delay.sec, so the delay is uniform in 0 to the interval plus reg_retry_random_interval. An interval of 0 (the default reg_first_retry_interval) and intervals of reg_retry_random_interval or more are unchanged. It also adds a sentence to the reg_retry_random_interval documentation, because the documented "interval ± reg_retry_random_interval" cannot apply below the jitter, where the lower end would be negative.
Suggested labels
component: pjsua-lib, type: bug.
Version and context
master 9192b71b6. macOS 26 on arm64, default configure; the code path is platform-independent.
Log
The "Scheduling re-registration retry for acc 1 in N seconds" values after the first retry, over 155 s with --rereg-delay=9: 25 retries, none longer than 9 s.
6 2 0 1 4 0 7 2 8 4 7 4 9 2 5 9 6 1 3 0 1 1 0 3 8
Activity