Added a "connect=<time>" option to callouts, for a separate timeout
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 4 Nov 2004 12:19:48 +0000 (12:19 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 4 Nov 2004 12:19:48 +0000 (12:19 +0000)
for making the connection. As part of this, the debug output for a
failed connection now shows the error, and, if it's a timeout, the
timeout value.

doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/acl.c
src/src/exim.c
src/src/functions.h
src/src/routers/rf_get_errors_address.c
src/src/smtp_in.c
src/src/smtp_out.c
src/src/verify.c

index a57b077..01bfcf8 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.14 2004/11/04 10:42:11 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.15 2004/11/04 12:19:48 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -56,6 +56,9 @@ Exim version 4.44
 
 14. Added forbid_sieve_filter and forbid_exim_filter to the redirect router.
 
+15. Added a new option "connect=<time>" to callout options, to set a different
+    connection timeout.
+
 
 Exim version 4.43
 -----------------
index b8cf61c..79e3476 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.5 2004/11/04 10:42:11 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.6 2004/11/04 12:19:48 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -33,6 +33,14 @@ Version 4.44
     options control which type(s) of filtering are permitted. By default, both
     Exim and Sieve filters are allowed.
 
+ 6. A new option for callouts makes it possible to set a different (usually
+    smaller) timeout for making the SMTP connection. The keyword is "connect".
+    For example:
+
+       verify = sender/callout=5s,connect=1s
+
+    If not specified, it defaults to the general timeout value.
+
 
 Version 4.43
 ------------
index 1812e0b..92ebc18 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/acl.c,v 1.4 2004/10/19 13:40:39 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.5 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -689,6 +689,7 @@ acl_verify(int where, address_item *addr, uschar *arg,
 int sep = '/';
 int callout = -1;
 int callout_overall = -1;
+int callout_connect = -1;
 int verify_options = 0;
 int rc;
 BOOL verify_header_sender = FALSE;
@@ -835,6 +836,11 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
         uschar *opt;
         uschar buffer[256];
         while (isspace(*ss)) ss++;
+        
+        /* This callout option handling code has become a mess as new options 
+        have been added in an ad hoc manner. It should be tidied up into some 
+        kind of table-driven thing. */
         while ((opt = string_nextinlist(&ss, &optsep, buffer, sizeof(buffer)))
               != NULL)
           {
@@ -903,6 +909,25 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
               return ERROR;
               }
             }
+          else if (strncmpic(opt, US"connect", 7) == 0)
+            {
+            opt += 7;
+            while (isspace(*opt)) opt++;
+            if (*opt++ != '=')
+              {
+              *log_msgptr = string_sprintf("'=' expected after "
+                "\"callout_overaall\" in ACL condition \"%s\"", arg);
+              return ERROR;
+              }
+            while (isspace(*opt)) opt++;
+            callout_connect = readconf_readtime(opt, 0, FALSE);
+            if (callout_connect < 0)
+              {
+              *log_msgptr = string_sprintf("bad time value in ACL condition "
+                "\"verify %s\"", arg);
+              return ERROR;
+              }
+            }
           else    /* Plain time is callout connect/command timeout */
             {
             callout = readconf_readtime(opt, 0, FALSE);
@@ -948,7 +973,7 @@ message if giving out verification details. */
 if (verify_header_sender)
   {
   rc = verify_check_header_address(user_msgptr, log_msgptr, callout,
-    callout_overall, se_mailfrom, pm_mailfrom, verify_options);
+    callout_overall, callout_connect, se_mailfrom, pm_mailfrom, verify_options);
   if (smtp_return_error_details)
     {
     if (*user_msgptr == NULL && *log_msgptr != NULL)
@@ -1031,7 +1056,7 @@ else if (verify_sender_address != NULL)
       verify_options. */
 
       rc = verify_address(sender_vaddr, NULL, verify_options, callout,
-        callout_overall, se_mailfrom, pm_mailfrom, &routed);
+        callout_overall, callout_connect, se_mailfrom, pm_mailfrom, &routed);
 
       HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
 
@@ -1083,7 +1108,7 @@ else
 
   addr2 = *addr;
   rc = verify_address(&addr2, NULL, verify_options|vopt_is_recipient, callout,
-    callout_overall, se_mailfrom, pm_mailfrom, NULL);
+    callout_overall, callout_connect, se_mailfrom, pm_mailfrom, NULL);
   HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
   *log_msgptr = addr2.message;
   *user_msgptr = addr2.user_message;
index 8f51e66..e22fd23 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.c,v 1.6 2004/10/19 11:40:52 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.7 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -640,7 +640,7 @@ if (address == NULL)
 else
   {
   int rc = verify_address(deliver_make_addr(address,TRUE), stdout, flags, -1,
-    -1, NULL, NULL, NULL);
+    -1, -1, NULL, NULL, NULL);
   if (rc == FAIL) *exit_value = 2;
     else if (rc == DEFER && *exit_value == 0) *exit_value = 1;
   }
index dbdf798..017ec87 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/functions.h,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/functions.h,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -292,10 +292,10 @@ extern int     tree_insertnode(tree_node **, tree_node *);
 extern tree_node *tree_search(tree_node *, uschar *);
 extern void    tree_write(tree_node *, FILE *);
 
-extern int     verify_address(address_item *, FILE *, int, int, int, uschar *,
-                 uschar *, BOOL *);
+extern int     verify_address(address_item *, FILE *, int, int, int, int,
+                 uschar *, uschar *, BOOL *);
 extern int     verify_check_dnsbl(uschar **);
-extern int     verify_check_header_address(uschar **, uschar **, int, int,
+extern int     verify_check_header_address(uschar **, uschar **, int, int, int,
                  uschar *, uschar *, int);
 extern int     verify_check_headers(uschar **);
 extern int     verify_check_host(uschar **);
index e2e7542..e0c3bc1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/rf_get_errors_address.c,v 1.1 2004/10/07 13:10:02 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/rf_get_errors_address.c,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -102,7 +102,7 @@ else
 
   DEBUG(D_route|D_verify)
     debug_printf("------ Verifying errors address %s ------\n", s);
-  if (verify_address(snew, NULL, vopt_is_recipient | vopt_qualify, -1, -1,
+  if (verify_address(snew, NULL, vopt_is_recipient | vopt_qualify, -1, -1, -1,
     NULL, NULL, NULL) == OK) *errors_to = snew->address;
   DEBUG(D_route|D_verify)
     debug_printf("------ End verifying errors address %s ------\n", s);
index 9189c67..e3b4dce 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.3 2004/10/19 11:29:25 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.4 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -3078,7 +3078,7 @@ while (done <= 0)
         {
         address_item *addr = deliver_make_addr(address, FALSE);
         switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1,
-               -1, NULL, NULL, NULL))
+               -1, -1, NULL, NULL, NULL))
           {
           case OK:
           s = string_sprintf("250 <%s> is deliverable", address);
@@ -3115,7 +3115,8 @@ while (done <= 0)
       BOOL save_log_testing_mode = log_testing_mode;
       address_test_mode = log_testing_mode = TRUE;
       (void) verify_address(deliver_make_addr(smtp_data, FALSE), smtp_out,
-        vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, NULL, NULL, NULL);
+        vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1, NULL, NULL, 
+        NULL);
       address_test_mode = FALSE;
       log_testing_mode = save_log_testing_mode;    /* true for -bh */
       }
index fc90c25..449b524 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_out.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_out.c,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -223,7 +223,13 @@ else if (ip_connect(sock, host_af, host->address, port, timeout) < 0)
 
 if (save_errno != 0)
   {
-  HDEBUG(D_transport|D_acl|D_v) debug_printf("failed\n");
+  HDEBUG(D_transport|D_acl|D_v) 
+    {
+    debug_printf("failed: %s", CUstrerror(save_errno));
+    if (save_errno == ETIMEDOUT) 
+      debug_printf(" (timeout=%s)", readconf_printtime(timeout));
+    debug_printf("\n");   
+    } 
   close(sock);
   errno = save_errno;
   return -1;
index bae410e..8b24fb4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/verify.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -123,7 +123,8 @@ Arguments:
   portstring        "port" option from transport, or NULL
   protocolstring    "protocol" option from transport, or NULL
   callout           the per-command callout timeout
-  callout_overall   the overall callout timeout (if < 0; use 4*callout)
+  callout_overall   the overall callout timeout (if < 0 use 4*callout)
+  callout_connect   the callout connection timeout (if < 0 use callout)
   options           the verification options - these bits are used:
                       vopt_is_recipient => this is a recipient address
                       vopt_callout_no_cache => don't use callout cache
@@ -138,8 +139,8 @@ Returns:            OK/FAIL/DEFER
 
 static int
 do_callout(address_item *addr, host_item *host_list, transport_feedback *tf,
-  int callout, int callout_overall, int options, uschar *se_mailfrom,
-  uschar *pm_mailfrom)
+  int callout, int callout_overall, int callout_connect, int options, 
+  uschar *se_mailfrom, uschar *pm_mailfrom)
 {
 BOOL is_recipient = (options & vopt_is_recipient) != 0;
 BOOL callout_no_cache = (options & vopt_callout_no_cache) != 0;
@@ -355,10 +356,11 @@ if (callout_random && callout_random_local_part != NULL)
       "callout_random_local_part: %s", expand_string_message);
   }
 
-/* Default the overall callout timeout if not set, and record the time we are
-starting so that we can enforce it. */
+/* Default the connect and overall callout timeouts if not set, and record the
+time we are starting so that we can enforce it. */
 
 if (callout_overall < 0) callout_overall = 4 * callout;
+if (callout_connect < 0) callout_connect = callout;
 callout_start_time = time(NULL);
 
 /* Now make connections to the hosts and do real callouts. The list of hosts
@@ -435,10 +437,10 @@ for (host = host_list; host != NULL && !done; host = host->next)
   outblock.authenticating = FALSE;
 
   /* Connect to the host; on failure, just loop for the next one, but we
-  set the error for the last one. */
+  set the error for the last one. Use the callout_connect timeout. */
 
   inblock.sock = outblock.sock =
-    smtp_connect(host, host_af, port, interface, callout, TRUE);
+    smtp_connect(host, host_af, port, interface, callout_connect, TRUE);
   if (inblock.sock < 0)
     {
     addr->message = string_sprintf("could not connect to %s [%s]: %s",
@@ -782,9 +784,10 @@ Arguments:
                      vopt_callout_recippmaster => use postmaster for recipient
 
   callout          if > 0, specifies that callout is required, and gives timeout
-                     for individual connections and commands
+                     for individual commands
   callout_overall  if > 0, gives overall timeout for the callout function;
                    if < 0, a default is used (see do_callout())
+  callout_connect  the connection timeout for callouts                  
   se_mailfrom      when callout is requested to verify a sender, use this
                      in MAIL FROM; NULL => ""
   pm_mailfrom      when callout is requested, if non-NULL, do the postmaster
@@ -800,7 +803,8 @@ Returns:           OK      address verified
 
 int
 verify_address(address_item *vaddr, FILE *f, int options, int callout,
-  int callout_overall, uschar *se_mailfrom, uschar *pm_mailfrom, BOOL *routed)
+  int callout_overall, int callout_connect, uschar *se_mailfrom, 
+  uschar *pm_mailfrom, BOOL *routed)
 {
 BOOL allok = TRUE;
 BOOL full_info = (f == NULL)? FALSE : (debug_selector != 0);
@@ -1054,7 +1058,7 @@ while (addr_new != NULL)
         else
           {
           rc = do_callout(addr, host_list, &tf, callout, callout_overall,
-            options, se_mailfrom, pm_mailfrom);
+            callout_connect, options, se_mailfrom, pm_mailfrom);
           }
         }
       else
@@ -1426,6 +1430,7 @@ Arguments:
   log_msgptr       points to where to put a log error message
   callout          timeout for callout check (passed to verify_address())
   callout_overall  overall callout timeout (ditto)
+  callout_connect  connect callout timeout (ditto) 
   se_mailfrom      mailfrom for verify; NULL => ""
   pm_mailfrom      sender for pm callout check (passed to verify_address())
   options          callout options (passed to verify_address())
@@ -1439,8 +1444,8 @@ Returns:           result of the verification attempt: OK, FAIL, or DEFER;
 
 int
 verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr,
-  int callout, int callout_overall, uschar *se_mailfrom, uschar *pm_mailfrom,
-  int options)
+  int callout, int callout_overall, int callout_connect, uschar *se_mailfrom, 
+  uschar *pm_mailfrom, int options)
 {
 static int header_types[] = { htype_sender, htype_reply_to, htype_from };
 int yield = FAIL;
@@ -1529,7 +1534,8 @@ for (i = 0; i < 3; i++)
           {
           vaddr = deliver_make_addr(address, FALSE);
           new_ok = verify_address(vaddr, NULL, options | vopt_fake_sender,
-            callout, callout_overall, se_mailfrom, pm_mailfrom, NULL);
+            callout, callout_overall, callout_connect, se_mailfrom, 
+            pm_mailfrom, NULL);
           }
         }