#define NKE_MAX_COOKIES 8
#define NKE_MAX_KEY_LENGTH SIV_MAX_KEY_LENGTH
+#define NKE_RETRY_FACTOR2_CONNECT 4
+#define NKE_RETRY_FACTOR2_TLS 10
+#define NKE_MAX_RETRY_INTERVAL2 19
+
typedef struct {
int length;
unsigned char key[NKE_MAX_KEY_LENGTH];
return i;
}
+
+/* ================================================== */
+
+int
+NKC_GetRetryFactor(NKC_Instance inst)
+{
+ return NKSN_GetRetryFactor(inst->session);
+}
NKE_Cookie *cookies, int *num_cookies, int max_cookies,
IPSockAddr *ntp_address);
+/* Get a factor to calculate retry interval (in log2 seconds) */
+extern int NKC_GetRetryFactor(NKC_Instance inst);
+
#endif
char *label;
gnutls_session_t tls_session;
SCH_TimeoutID timeout_id;
+ int retry_factor;
struct Message message;
int new_message;
LOG(inst->server ? LOGS_DEBUG : LOGS_ERR,
"TLS handshake with %s failed : %s", inst->label, gnutls_strerror(r));
stop_session(inst);
+
+ /* Increase the retry interval if the handshake did not fail due
+ to the other end closing the connection */
+ if (r != GNUTLS_E_PULL_ERROR && r != GNUTLS_E_PREMATURE_TERMINATION)
+ inst->retry_factor = NKE_RETRY_FACTOR2_TLS;
+
return 0;
}
return 0;
}
+ inst->retry_factor = NKE_RETRY_FACTOR2_TLS;
+
if (DEBUG) {
char *description = gnutls_session_get_desc(inst->tls_session);
DEBUG_LOG("Handshake with %s completed %s",
inst->label = NULL;
inst->tls_session = NULL;
inst->timeout_id = 0;
+ inst->retry_factor = NKE_RETRY_FACTOR2_CONNECT;
return inst;
}
inst->label = Strdup(label);
inst->timeout_id = SCH_AddTimeoutByDelay(timeout, session_timeout, inst);
+ inst->retry_factor = NKE_RETRY_FACTOR2_CONNECT;
reset_message(&inst->message);
inst->new_message = 0;
{
stop_session(inst);
}
+
+/* ================================================== */
+
+int
+NKSN_GetRetryFactor(NKSN_Instance inst)
+{
+ return inst->retry_factor;
+}
/* Stop the session */
extern void NKSN_StopSession(NKSN_Instance inst);
+/* Get a factor to calculate retry interval (in log2 seconds)
+ based on the session state or how it was terminated */
+extern int NKSN_GetRetryFactor(NKSN_Instance inst);
+
#endif
SIV_Instance siv_s2c;
NKC_Instance nke;
- double last_nke_attempt;
+ int nke_attempts;
+ double next_nke_attempt;
double last_nke_success;
NKE_Cookie cookies[NTS_MAX_COOKIES];
int num_cookies;
static void
reset_instance(NNC_Instance inst)
{
- inst->last_nke_attempt = -MIN_NKE_RETRY_INTERVAL;
+ inst->nke_attempts = 0;
+ inst->next_nke_attempt = 0.0;
inst->last_nke_success = 0.0;
inst->num_cookies = 0;
inst->cookie_index = 0;
/* ================================================== */
+static void
+update_next_nke_attempt(NNC_Instance inst, double now)
+{
+ int factor, interval;
+
+ if (!inst->nke)
+ return;
+
+ factor = NKC_GetRetryFactor(inst->nke);
+ interval = MIN(factor + inst->nke_attempts - 1, NKE_MAX_RETRY_INTERVAL2);
+ inst->next_nke_attempt = now + UTI_Log2ToDouble(interval);
+}
+
+/* ================================================== */
+
static int
get_nke_data(NNC_Instance inst)
{
now = SCH_GetLastEventMonoTime();
if (!inst->nke) {
- if (now - inst->last_nke_attempt < MIN_NKE_RETRY_INTERVAL) {
- DEBUG_LOG("Limiting NTS-KE request rate");
+ if (now < inst->next_nke_attempt) {
+ DEBUG_LOG("Limiting NTS-KE request rate (%f seconds)",
+ inst->next_nke_attempt - now);
return 0;
}
inst->nke = NKC_CreateInstance(&inst->nts_address, inst->name);
+ inst->nke_attempts++;
+ update_next_nke_attempt(inst, now);
+
if (!NKC_Start(inst->nke))
return 0;
-
- inst->last_nke_attempt = now;
}
+ update_next_nke_attempt(inst, now);
+
if (NKC_IsActive(inst->nke))
return 0;
/* At this point we know the client interoperates with the server. Allow a
new NTS-KE session to be started as soon as the cookies run out. */
- inst->last_nke_attempt = -MIN_NKE_RETRY_INTERVAL;
+ inst->nke_attempts = 0;
+ inst->next_nke_attempt = 0.0;
return 1;
}
TEST_CHECK(!NNC_GenerateRequestAuth(inst, &packet, &info));
while (!NNC_PrepareForAuth(inst)) {
- inst->last_nke_attempt = random() % 100000 - 50000;
+ inst->next_nke_attempt = SCH_GetLastEventMonoTime() + random() % 10 - 7;
}
TEST_CHECK(inst->num_cookies > 0);