Copyright updates:
[exim.git] / src / src / structs.h
index 6666c52caea34fc321fc11e0867bd17aaa202b23..214819482ff8fc99e96f1281d4a33b8a0f1c494e 100644 (file)
@@ -2,8 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 
 /* Definitions of various structures. In addition, those that are visible for
@@ -25,13 +27,22 @@ struct smtp_outblock;
 struct transport_info;
 struct router_info;
 
+/* Growable-string */
+typedef struct gstring {
+  int  size;           /* Current capacity of string memory */
+  int  ptr;            /* Offset at which to append further chars */
+  uschar * s;          /* The string memory */
+} gstring;
+
 /* Structure for remembering macros for the configuration file */
 
 typedef struct macro_item {
-  struct  macro_item *next;
-  BOOL    command_line;
-  uschar *replacement;
-  uschar  name[1];
+  struct  macro_item * next;
+  BOOL         command_line;
+  unsigned     namelen;
+  unsigned     replen;
+  const uschar * name;
+  const uschar * replacement;
 } macro_item;
 
 /* Structure for bit tables for debugging and logging */
@@ -51,6 +62,17 @@ typedef struct ugid_block {
   BOOL    initgroups;
 } ugid_block;
 
+typedef enum { CHUNKING_NOT_OFFERED = -1,
+               CHUNKING_OFFERED,
+               CHUNKING_ACTIVE,
+               CHUNKING_LAST} chunking_state_t;
+
+typedef enum { TFO_NOT_USED = 0,
+               TFO_ATTEMPTED_NODATA,
+               TFO_ATTEMPTED_DATA,
+               TFO_USED_NODATA,
+               TFO_USED_DATA } tfo_state_t;
+
 /* Structure for holding information about a host for use mainly by routers,
 but also used when checking lists of hosts and when transporting. Looking up
 host addresses is done using this structure. */
@@ -59,14 +81,17 @@ typedef enum {DS_UNK=-1, DS_NO, DS_YES} dnssec_status_t;
 
 typedef struct host_item {
   struct host_item *next;
-  const uschar *name;             /* Host name */
-  const uschar *address;          /* IP address in text form */
-  int     port;                   /* port value in host order (if SRV lookup) */
-  int     mx;                     /* MX value if found via MX records */
-  int     sort_key;               /* MX*1000 plus random "fraction" */
-  int     status;                 /* Usable, unusable, or unknown */
-  int     why;                    /* Why host is unusable */
-  int     last_try;               /* Time of last try if known */
+  const uschar *name;          /* Host name */
+#ifndef DISABLE_TLS
+  const uschar *certname;      /* Name used for certificate checks */
+#endif
+  const uschar *address;       /* IP address in text form */
+  int     port;                        /* port value in host order (if SRV lookup) */
+  int     mx;                  /* MX value if found via MX records */
+  int     sort_key;            /* MX*1000 plus random "fraction" */
+  int     status;              /* Usable, unusable, or unknown */
+  int     why;                 /* Why host is unusable */
+  int     last_try;            /* Time of last try if known */
   dnssec_status_t dnssec;
 } host_item;
 
@@ -109,11 +134,15 @@ typedef struct driver_instance {
   uschar *name;                   /* Instance name */
   struct driver_info *info;       /* Points to info for this driver */
   void   *options_block;          /* Pointer to private options */
+
   uschar *driver_name;            /* All start with this generic option */
+  const uschar *srcfile;         /* and config source info for errors */
+  int    srcline;
 } driver_instance;
 
 typedef struct driver_info {
   uschar *driver_name;            /* Name of driver */
+
   optionlist *options;            /* Table of private options names */
   int    *options_count;          /* -> Number of entries in table */
   void   *options_block;          /* Points to default private block */
@@ -135,6 +164,9 @@ typedef struct transport_instance {
   struct transport_info *info;    /* Info for this driver */
   void *options_block;            /* Pointer to private options */
   uschar *driver_name;            /* Must be first */
+  const uschar *srcfile;
+  int    srcline;
+
   int   (*setup)(                 /* Setup entry point */
     struct transport_instance *,
     struct address_item *,
@@ -151,7 +183,7 @@ typedef struct transport_instance {
   uschar *expand_multi_domain;    /* )                                  */
   BOOL    multi_domain;           /* )                                  */
   BOOL    overrides_hosts;        /* ) Used only for remote transports  */
-  int     max_addresses;          /* )                                  */
+  uschar *max_addresses;          /* )                                  */
   int     connection_max_messages;/* )                                  */
                                   /**************************************/
   BOOL    deliver_as_creator;     /* Used only by pipe at present */
@@ -218,14 +250,30 @@ typedef struct transport_info {
 } transport_info;
 
 
+/* smtp transport datachunk callback */
+
+#define tc_reap_prev   BIT(0)  /* Flags: reap previous SMTP cmd responses */
+#define tc_chunk_last  BIT(1)  /* annotate chunk SMTP cmd as LAST */
+
+struct transport_context;
+typedef int (*tpt_chunk_cmd_cb)(struct transport_context *, unsigned, unsigned);
+
 /* Structure for information about a delivery-in-progress */
 
 typedef struct transport_context {
-  transport_instance * tblock;
-  struct address_item * addr;
-  uschar       * check_string;
-  uschar       * escape_string;
-  int            options;              /* topt_* */
+  union {                      /* discriminated by option topt_output_string */
+    int                          fd;   /* file descriptor to write message to */
+    gstring *            msg;  /* allocated string with written message */
+  } u;
+  transport_instance   * tblock;               /* transport */
+  struct address_item  * addr;
+  uschar               * check_string;         /* string replacement */
+  uschar               * escape_string;
+  int                    options;              /* output processing topt_* */
+
+  /* items below only used with option topt_use_bdat */
+  tpt_chunk_cmd_cb       chunk_cb;             /* per-datachunk callback */
+  void                 * smtp_context;
 } transport_ctx;
 
 
@@ -243,6 +291,8 @@ typedef struct router_instance {
   struct router_info *info;
   void   *options_block;          /* Pointer to private options */
   uschar *driver_name;            /* Must be first */
+  const uschar *srcfile;
+  int    srcline;
 
   uschar *address_data;           /* Arbitrary data */
 #ifdef EXPERIMENTAL_BRIGHTMAIL
@@ -297,6 +347,7 @@ typedef struct router_instance {
   BOOL    retry_use_local_part;   /* Just what it says */
   BOOL    same_domain_copy_routing; /* TRUE => copy routing for same domain */
   BOOL    self_rewrite;           /* TRUE to rewrite headers if making local */
+  uschar *set;                   /* Variable = value to set; list */
   BOOL    suffix_optional;        /* As it says */
   BOOL    verify_only;            /* Skip this router if not verifying */
   BOOL    verify_recipient;       /* Use this router when verifying a recipient*/
@@ -359,6 +410,9 @@ typedef struct auth_instance {
   struct auth_info *info;         /* Pointer to driver info block */
   void   *options_block;          /* Pointer to private options */
   uschar *driver_name;            /* Must be first */
+  const uschar *srcfile;
+  int    srcline;
+
   uschar *advertise_condition;    /* Are we going to advertise this?*/
   uschar *client_condition;       /* Should the client try this? */
   uschar *public_name;            /* Advertised name */
@@ -390,13 +444,13 @@ typedef struct auth_info {
     uschar *);                    /* rest of AUTH command */
   int (*clientcode)(              /* client function */
     struct auth_instance *,
-    struct smtp_inblock *,        /* socket and input buffer */
-    struct smtp_outblock *,       /* socket and output buffer */
+    void *,                      /* smtp conn, with socket, output and input buffers */
     int,                          /* command timeout */
     uschar *,                     /* buffer for reading response */
     int);                         /* sizeof buffer */
-  void (*version_report)(         /* diagnostic version reporting */
-    FILE *);                      /* I/O stream to print to */
+  gstring * (*version_report)(    /* diagnostic version reporting */
+    gstring *);                   /* string to append to */
+  void (*macros_create)(void);   /* feature-macro creation */
 } auth_info;
 
 
@@ -409,13 +463,14 @@ typedef struct ip_address_item {
   int    port;
   BOOL   v6_include_v4;            /* Used in the daemon */
   uschar address[46];
+  uschar * log;                           /* portion of "listening on" log line */
 } ip_address_item;
 
 /* Structure for chaining together arbitrary strings. */
 
 typedef struct string_item {
-  struct string_item *next;
-  uschar *text;
+  struct string_item * next;
+  uschar *             text;
 } string_item;
 
 /* Information about a soft delivery failure, for use when calculating
@@ -474,60 +529,16 @@ typedef struct address_item_propagated {
   uschar *errors_address;         /* where to send errors (NULL => sender) */
   header_line *extra_headers;     /* additional headers */
   uschar *remove_headers;         /* list of those to remove */
+  void   *variables;             /* router-vasriables */
 
-  #ifdef EXPERIMENTAL_SRS
-  uschar *srs_sender;             /* Change return path when delivering */
-  #endif
-  #ifdef SUPPORT_I18N
+  BOOL    ignore_error:1;        /* ignore delivery error */
+#ifdef SUPPORT_I18N
   BOOL    utf8_msg:1;            /* requires SMTPUTF8 processing */
   BOOL   utf8_downcvt:1;         /* mandatory downconvert on delivery */
   BOOL   utf8_downcvt_maybe:1;   /* optional downconvert on delivery */
-  #endif
-} address_item_propagated;
-
-/* Bits for the flags field below */
-
-#define af_allow_file          0x00000001 /* allow file in generated address */
-#define af_allow_pipe          0x00000002 /* allow pipe in generated address */
-#define af_allow_reply         0x00000004 /* allow autoreply in generated address */
-#define af_dr_retry_exists     0x00000008 /* router retry record exists */
-#define af_expand_pipe         0x00000010 /* expand pipe arguments */
-#define af_file                0x00000020 /* file delivery; always with pfr */
-#define af_gid_set             0x00000040 /* gid field is set */
-#define af_home_expanded       0x00000080 /* home_dir is already expanded */
-#define af_ignore_error        0x00000100 /* ignore delivery error */
-#define af_initgroups          0x00000200 /* use initgroups() for local transporting */
-#define af_local_host_removed  0x00000400 /* local host was backup */
-#define af_lt_retry_exists     0x00000800 /* local transport retry exists */
-#define af_pfr                 0x00001000 /* pipe or file or reply delivery */
-#define af_retry_skipped       0x00002000 /* true if retry caused some skipping */
-#define af_retry_timedout      0x00004000 /* true if retry timed out */
-#define af_uid_set             0x00008000 /* uid field is set */
-#define af_hide_child          0x00010000 /* hide child in bounce/defer msgs */
-#define af_sverify_told        0x00020000 /* sender verify failure notified */
-#define af_verify_pmfail       0x00040000 /* verify failure was postmaster callout */
-#define af_verify_nsfail       0x00080000 /* verify failure was null sender callout */
-#define af_homonym             0x00100000 /* an ancestor has same address */
-#define af_verify_routed       0x00200000 /* for cached sender verify: routed OK */
-#define af_verify_callout      0x00400000 /* for cached sender verify: callout was specified */
-#define af_include_affixes     0x00800000 /* delivered with affixes in RCPT */
-#define af_cert_verified       0x01000000 /* delivered with verified TLS cert */
-#define af_pass_message        0x02000000 /* pass message in bounces */
-#define af_bad_reply           0x04000000 /* filter could not generate autoreply */
-#ifndef DISABLE_PRDR
-# define af_prdr_used          0x08000000 /* delivery used SMTP PRDR */
-#endif
-#define af_force_command       0x10000000 /* force_command in pipe transport */
-#ifdef EXPERIMENTAL_DANE
-# define af_dane_verified      0x20000000 /* TLS cert verify done with DANE */
 #endif
-#ifdef SUPPORT_I18N
-# define af_utf8_downcvt       0x40000000 /* downconvert was done for delivery */
-#endif
-
-/* These flags must be propagated when a child is created */
+} address_item_propagated;
 
-#define af_propagate           (af_ignore_error)
 
 /* The main address structure. Note that fields that are to be copied to
 generated addresses should be put in the address_item_propagated structure (see
@@ -556,7 +567,9 @@ typedef struct address_item {
   uschar *lc_local_part;          /* lowercased local part */
   uschar *local_part;             /* points to cc or lc version */
   uschar *prefix;                 /* stripped prefix of local part */
+  uschar *prefix_v;              /*  variable part of above */
   uschar *suffix;                 /* stripped suffix of local part */
+  uschar *suffix_v;              /*  variable part of above */
   const uschar *domain;           /* working domain (lower cased) */
 
   uschar *address_retry_key;      /* retry key including full address */
@@ -573,7 +586,8 @@ typedef struct address_item {
   uschar *self_hostname;          /* after self=pass */
   uschar *shadow_message;         /* info about shadow transporting */
 
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
+  const uschar *tlsver;           /* version used for transport */
   uschar *cipher;                 /* Cipher used for transport */
   void   *ourcert;                /* Certificate offered to peer, binary */
   void   *peercert;               /* Certificate from peer, binary */
@@ -597,15 +611,67 @@ typedef struct address_item {
   uid_t   uid;                    /* uid for transporting */
   gid_t   gid;                    /* gid for transporting */
 
-  unsigned int flags;             /* a row of bits, defined above */
+                                 /* flags */
+  struct {
+    BOOL af_allow_file:1;              /* allow file in generated address */
+    BOOL af_allow_pipe:1;              /* allow pipe in generated address */
+    BOOL af_allow_reply:1;             /* allow autoreply in generated address */
+    BOOL af_dr_retry_exists:1;         /* router retry record exists */
+    BOOL af_expand_pipe:1;             /* expand pipe arguments */
+    BOOL af_file:1;                    /* file delivery; always with pfr */
+    BOOL af_gid_set:1;                 /* gid field is set */
+    BOOL af_home_expanded:1;           /* home_dir is already expanded */
+    BOOL af_initgroups:1;              /* use initgroups() for local transporting */
+    BOOL af_local_host_removed:1;      /* local host was backup */
+    BOOL af_lt_retry_exists:1;         /* local transport retry exists */
+    BOOL af_pfr:1;                     /* pipe or file or reply delivery */
+    BOOL af_retry_skipped:1;           /* true if retry caused some skipping */
+    BOOL af_retry_timedout:1;          /* true if retry timed out */
+    BOOL af_uid_set:1;                 /* uid field is set */
+    BOOL af_hide_child:1;              /* hide child in bounce/defer msgs */
+    BOOL af_sverify_told:1;            /* sender verify failure notified */
+    BOOL af_verify_pmfail:1;           /* verify failure was postmaster callout */
+    BOOL af_verify_nsfail:1;           /* verify failure was null sender callout */
+    BOOL af_homonym:1;                 /* an ancestor has same address */
+    BOOL af_verify_routed:1;           /* for cached sender verify: routed OK */
+    BOOL af_verify_callout:1;          /* for cached sender verify: callout was specified */
+    BOOL af_include_affixes:1;         /* delivered with affixes in RCPT */
+    BOOL af_new_conn:1;                        /* delivered on an fresh TCP conn */
+    BOOL af_cont_conn:1;               /* delivered (with new MAIL cmd) on an existing TCP conn */
+    BOOL af_cert_verified:1;           /* delivered with verified TLS cert */
+    BOOL af_pass_message:1;            /* pass message in bounces */
+    BOOL af_bad_reply:1;               /* filter could not generate autoreply */
+    BOOL af_tcp_fastopen_conn:1;       /* delivery connection used TCP Fast Open */
+    BOOL af_tcp_fastopen:1;            /* delivery usefully used TCP Fast Open */
+    BOOL af_tcp_fastopen_data:1;       /* delivery sent SMTP commands on TCP Fast Open */
+    BOOL af_pipelining:1;              /* delivery used (traditional) pipelining */
+#ifndef DISABLE_PIPE_CONNECT
+    BOOL af_early_pipe:1;              /* delivery used connect-time pipelining */
+#endif
+#ifndef DISABLE_PRDR
+    BOOL af_prdr_used:1;               /* delivery used SMTP PRDR */
+#endif
+    BOOL af_chunking_used:1;           /* delivery used SMTP CHUNKING */
+    BOOL af_force_command:1;           /* force_command in pipe transport */
+#ifdef SUPPORT_DANE
+    BOOL af_dane_verified:1;           /* TLS cert verify done with DANE */
+#endif
+#ifdef SUPPORT_I18N
+    BOOL af_utf8_downcvt:1;            /* downconvert was done for delivery */
+#endif
+#ifndef DISABLE_TLS_RESUME
+    BOOL af_tls_resume:1;              /* TLS used a resumed session */
+#endif
+  } flags;
+
   unsigned int domain_cache[(MAX_NAMED_LIST * 2)/32];
   unsigned int localpart_cache[(MAX_NAMED_LIST * 2)/32];
   int     mode;                   /* mode for local transporting to a file */
+  int    basic_errno;            /* status after failure */
   int     more_errno;             /* additional error information */
-                                  /* (may need to hold a timestamp) */
+  struct timeval delivery_time;   /* time taken to do delivery/attempt */
 
-  short int basic_errno;          /* status after failure */
-  short int child_count;          /* number of child addresses */
+  unsigned short child_count;     /* number of child addresses */
   short int return_file;          /* fileno of return data file */
   short int special_action;       /* ( used when when deferred or failed */
                                   /* (  also  */
@@ -677,11 +743,17 @@ typedef struct tree_node {
 /* Structure for holding time-limited data such as DNS returns.
 We use this rather than extending tree_node to avoid wasting
 space for most tree use (variables...) at the cost of complexity
-for the lookups cache */
+for the lookups cache.
+We also store any options used for the lookup. */
 
 typedef struct expiring_data {
-  time_t expiry;                 /* if nonzero, data invalid after this time */
-  void   *ptr;                   /* pointer to data */
+  time_t       expiry;         /* if nonzero, data invalid after this time */
+  const uschar * opts;         /* options, or NULL */
+  union
+    {
+    void  *    ptr;            /* pointer to data */
+    int                val;            /* or integer data */
+    } data;
 } expiring_data;
 
 /* Structure for holding the handle and the cached last lookup for searches.
@@ -701,27 +773,28 @@ typedef struct search_cache {
 uncompressed, but the data pointer is into the raw data. */
 
 typedef struct {
-  uschar  name[DNS_MAXNAME];      /* domain name */
-  int     type;                   /* record type */
-  unsigned short ttl;            /* time-to-live, seconds */
-  int     size;                   /* size of data */
-  uschar *data;                   /* pointer to data */
+  uschar        name[DNS_MAXNAME];      /* domain name */
+  int           type;                   /* record type */
+  unsigned short ttl;                  /* time-to-live, seconds */
+  int           size;                   /* size of data */
+  const uschar *data;                   /* pointer to data */
 } dns_record;
 
-/* Structure for holding the result of a DNS query. */
+/* Structure for holding the result of a DNS query.  A touch over
+64k big, so take care to release as soon as possible. */
 
 typedef struct {
   int     answerlen;              /* length of the answer */
-  uschar  answer[MAXPACKET];      /* the answer itself */
+  uschar  answer[NS_MAXMSG];      /* the answer itself */
 } dns_answer;
 
 /* Structure for holding the intermediate data while scanning a DNS answer
 block. */
 
 typedef struct {
-  int     rrcount;                /* count of RRs in the answer */
-  uschar *aptr;                   /* pointer in the answer while scanning */
-  dns_record srr;                 /* data from current record in scan */
+  int            rrcount;         /* count of RRs in the answer */
+  const uschar *aptr;             /* pointer in the answer while scanning */
+  dns_record     srr;             /* data from current record in scan */
 } dns_scan;
 
 /* Structure for holding a chain of IP addresses that are extracted from
@@ -749,15 +822,40 @@ md5;
 typedef struct sha1 {
   unsigned int H[5];
   unsigned int length;
-  }
-sha1;
+} sha1;
+
+/* Information for making an smtp connection */
+typedef struct {
+  transport_instance *  tblock;
+  void *               ob;     /* smtp_transport_options_block * */
+  host_item *           host;
+  int                   host_af;
+  uschar *              interface;
+
+  int                  sock;   /* used for a bound but not connected socket */
+  uschar *             sending_ip_address;     /* used for TLS resumption */
+  const uschar *       host_lbserver;          /* ditto, for server-behind LB */
+  BOOL                 have_lbserver:1;        /* host_lbserver is valid */
+
+#ifdef SUPPORT_DANE
+  BOOL dane:1;                 /* connection must do dane */
+  dns_answer           tlsa_dnsa;      /* strictly, this should use tainted mem */
+#endif
+} smtp_connect_args;
+
+/* A client-initiated connection. If TLS, the second element is non-NULL */
+typedef struct {
+  int  sock;
+  void * tls_ctx;
+} client_conn_ctx;
+
 
 /* Structure used to hold incoming packets of SMTP responses for a specific
 socket. The packets which may contain multiple lines (and in some cases,
 multiple responses). */
 
 typedef struct smtp_inblock {
-  int     sock;                   /* the socket */
+  client_conn_ctx * cctx;        /* the connection */
   int     buffersize;             /* the size of the buffer */
   uschar *ptr;                    /* current position in the buffer */
   uschar *ptrend;                 /* end of data in the buffer */
@@ -769,12 +867,14 @@ specific socket. The packets which may contain multiple lines when pipelining
 is in use. */
 
 typedef struct smtp_outblock {
-  int     sock;                   /* the socket */
+  client_conn_ctx * cctx;        /* the connection */
   int     cmd_count;              /* count of buffered commands */
   int     buffersize;             /* the size of the buffer */
   BOOL    authenticating;         /* TRUE when authenticating */
   uschar *ptr;                    /* current position in the buffer */
   uschar *buffer;                 /* the buffer itself */
+
+  smtp_connect_args * conn_args;  /* to make connection, if not yet made */
 } smtp_outblock;
 
 /* Structure to hold information about the source of redirection information */
@@ -796,7 +896,7 @@ typedef struct check_host_block {
   const uschar *host_name;
   const uschar *host_address;
   const uschar *host_ipv4;
-  BOOL   negative;
+  mcs_flags    flags;
 } check_host_block;
 
 /* Structure for remembering lookup data when caching the result of
@@ -811,27 +911,30 @@ typedef struct namedlist_cacheblock {
 /* Structure for holding data for an entry in a named list */
 
 typedef struct namedlist_block {
-  const uschar *string;              /* the list string */
-  namedlist_cacheblock *cache_data;  /* cached domain_data or localpart_data */
-  int number;                        /* the number of the list for caching */
+  const uschar *string;                        /* the list string */
+  namedlist_cacheblock *cache_data;    /* cached domain_data or localpart_data */
+  short                number;                 /* the number of the list for caching */
+  BOOL         hide;                   /* -bP does not display value */
 } namedlist_block;
 
 /* Structures for Access Control Lists */
 
 typedef struct acl_condition_block {
-  struct acl_condition_block *next;
-  uschar *arg;
-  int type;
+  struct acl_condition_block * next;
+  uschar *                     arg;
+  int                          type;
   union {
-    BOOL negated;
-    uschar *varname;
+    BOOL       negated;
+    uschar *   varname;
   } u;
 } acl_condition_block;
 
 typedef struct acl_block {
-  struct acl_block *next;
-  acl_condition_block *condition;
-  int verb;
+  struct acl_block *   next;
+  acl_condition_block *        condition;
+  int                  verb;
+  int                  srcline;
+  const uschar *       srcfile;
 } acl_block;
 
 /* smtp transport calc outbound_ip */
@@ -840,11 +943,37 @@ typedef BOOL (*oicf) (uschar *message_id, void *data);
 /* DKIM information for transport */
 struct ob_dkim {
   uschar *dkim_domain;
+  uschar *dkim_identity;
   uschar *dkim_private_key;
   uschar *dkim_selector;
   uschar *dkim_canon;
   uschar *dkim_sign_headers;
   uschar *dkim_strict;
-} dkim;
+  uschar *dkim_hash;
+  uschar *dkim_timestamps;
+  BOOL    dot_stuffed;
+  BOOL    force_bodyhash;
+#ifdef EXPERIMENTAL_ARC
+  uschar *arc_signspec;
+#endif
+};
+
+
+/* per-queue-runner info */
+typedef struct qrunner {
+  struct qrunner * next;       /* list sorted by next tick */
+
+  uschar *     name;           /* NULL for the default queue */
+  unsigned     interval;       /* tick rate, seconds */
+  time_t       next_tick;      /* next run should, or should have, start(ed) */
+  unsigned     run_max;        /* concurrent queue runner limit */
+  unsigned     run_count;      /* current runners */
+
+  BOOL queue_run_force :1;
+  BOOL deliver_force_thaw :1;
+  BOOL queue_run_first_delivery :1;
+  BOOL queue_run_local :1;
+  BOOL queue_2stage :1;
+} qrunner;
 
 /* End of structs.h */