Drop server_realm from heimdal_gssapi
[exim.git] / src / src / retry.c
index eb4cd46cc18900189a3b0d20fe10295615ef037f..e877bf7d0157d7d3eba76d3c66c16a11ad89744b 100644 (file)
@@ -1,10 +1,8 @@
-/* $Cambridge: exim/src/src/retry.c,v 1.7 2006/02/09 14:50:58 ph10 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with retrying unsuccessful deliveries. */
@@ -47,9 +45,8 @@ if (retry != NULL && retry->rules != NULL)
        last_rule->next != NULL;
        last_rule = last_rule->next);
   DEBUG(D_transport|D_retry)
-    debug_printf("now=%d received_time=%d diff=%d timeout=%d\n",
-      (int)now, received_time, (int)(now - received_time),
-      last_rule->timeout);
+    debug_printf("  received_time=%d diff=%d timeout=%d\n",
+      received_time, (int)(now - received_time), last_rule->timeout);
   address_timeout = (now - received_time > last_rule->timeout);
   }
 else
@@ -210,8 +207,14 @@ if (host_retry_record != NULL)
   if (now < host_retry_record->next_try && !deliver_force)
     {
     DEBUG(D_transport|D_retry)
+      {
       debug_printf("host retry time not reached: checking ultimate address "
         "timeout\n");
+      debug_printf("  now=%d first_failed=%d next_try=%d expired=%d\n",
+        (int)now, (int)host_retry_record->first_failed,
+        (int)host_retry_record->next_try,
+        host_retry_record->expired);
+      }
 
     if (!host_retry_record->expired &&
         ultimate_address_timeout(host_key, domain,
@@ -247,8 +250,13 @@ if (message_retry_record != NULL)
   if (now < message_retry_record->next_try && !deliver_force)
     {
     DEBUG(D_transport|D_retry)
+      {
       debug_printf("host+message retry time not reached: checking ultimate "
         "address timeout\n");
+      debug_printf("  now=%d first_failed=%d next_try=%d expired=%d\n",
+        (int)now, (int)message_retry_record->first_failed,
+        (int)message_retry_record->next_try, message_retry_record->expired);
+      }
     if (!ultimate_address_timeout(host_key, domain, 0, 0, now))
       {
       host->status = hstatus_unusable;
@@ -414,20 +422,31 @@ for (yield = retries; yield != NULL; yield = yield->next)
         continue;
       }
 
-    /* Handle 4xx responses to RCPT. The code that was received is in the 2nd
-    least significant byte of more_errno (with 400 subtracted). The required
-    value is coded in the 2nd least significant byte of the yield->more_errno
-    field as follows:
+    /* The TLSREQUIRED error also covers TLSFAILURE. These are subtly different
+    errors, but not worth separating at this level. */
+
+    else if (yield->basic_errno == ERRNO_TLSREQUIRED)
+      {
+      if (basic_errno != ERRNO_TLSREQUIRED && basic_errno != ERRNO_TLSFAILURE)
+        continue;
+      }
+
+    /* Handle 4xx responses to MAIL, RCPT, or DATA. The code that was received
+    is in the 2nd least significant byte of more_errno (with 400 subtracted).
+    The required value is coded in the 2nd least significant byte of the
+    yield->more_errno field as follows:
 
       255     => any 4xx code
       >= 100  => the decade must match the value less 100
       < 100   => the exact value must match
     */
 
-    else if (yield->basic_errno == ERRNO_RCPT4XX)
+    else if (yield->basic_errno == ERRNO_MAIL4XX ||
+             yield->basic_errno == ERRNO_RCPT4XX ||
+             yield->basic_errno == ERRNO_DATA4XX)
       {
       int wanted;
-      if (basic_errno != ERRNO_RCPT4XX) continue;
+      if (basic_errno != yield->basic_errno) continue;
       wanted = (yield->more_errno >> 8) & 255;
       if (wanted != 255)
         {
@@ -687,13 +706,14 @@ for (i = 0; i < 3; i++)
         DEBUG(D_retry) debug_printf("failing_interval=%d message_age=%d\n",
           failing_interval, message_age);
 
-        /* If the message has been on the queue longer than the recorded time
-        of failure, use the message's age instead. This can happen when some
-        messages can be delivered and others cannot; a successful delivery will
-        reset the first_failed time, and this can lead to a failing message
-        being retried too often. */
+        /* For a non-host error, if the message has been on the queue longer
+        than the recorded time of failure, use the message's age instead. This
+        can happen when some messages can be delivered and others cannot; a
+        successful delivery will reset the first_failed time, and this can lead
+        to a failing message being retried too often. */
 
-        if (message_age > failing_interval) failing_interval = message_age;
+        if ((rti->flags & rf_host) == 0 && message_age > failing_interval)
+          failing_interval = message_age;
 
         /* Search for the current retry rule. The cutoff time of the
         last rule is handled differently to the others. The rule continues
@@ -798,7 +818,8 @@ for (i = 0; i < 3; i++)
               {
               next_try = now + rule->p1;
               if (next_gap > rule->p1)
-                next_try += random_number(next_gap - rule->p1);
+                next_try += random_number(next_gap - rule->p1)/2 +
+                  (next_gap - rule->p1)/2;
               }
             }
           }