Browse Source

misc: reduce struct and struct field sizes

- by using BIT() instead of bool
- imap: shrink struct
- ftp: make state 'unsigned char'
- ftp: sort ftp_conn struct entries on size
- urldata: use smaller fields for SSL version info storage
- pop3: reduce the pop3_conn struct size
- smtp: reduce the size of the smtp structs

Closes #10186
Daniel Stenberg 1 year ago
parent
commit
1485e89213
12 changed files with 82 additions and 71 deletions
  1. 3 3
      lib/curl_sasl.h
  2. 3 5
      lib/ftp.c
  3. 25 24
      lib/ftp.h
  4. 8 4
      lib/imap.c
  5. 11 11
      lib/imap.h
  6. 6 2
      lib/pop3.c
  7. 5 5
      lib/pop3.h
  8. 2 2
      lib/setopt.c
  9. 6 2
      lib/smtp.c
  10. 9 9
      lib/smtp.h
  11. 2 2
      lib/urldata.h
  12. 2 2
      lib/vtls/vtls.c

+ 3 - 3
lib/curl_sasl.h

@@ -125,9 +125,9 @@ struct SASL {
   unsigned short authmechs;  /* Accepted authentication mechanisms */
   unsigned short prefmech;   /* Preferred authentication mechanism */
   unsigned short authused;   /* Auth mechanism used for the connection */
-  bool resetprefs;           /* For URL auth option parsing. */
-  bool mutual_auth;          /* Mutual authentication enabled (GSSAPI only) */
-  bool force_ir;             /* Protocol always supports initial response */
+  BIT(resetprefs);           /* For URL auth option parsing. */
+  BIT(mutual_auth);          /* Mutual authentication enabled (GSSAPI only) */
+  BIT(force_ir);             /* Protocol always supports initial response */
 };
 
 /* This is used to test whether the line starts with the given mechanism */

+ 3 - 5
lib/ftp.c

@@ -2554,13 +2554,11 @@ static CURLcode ftp_state_loggedin(struct Curl_easy *data)
 
 /* for USER and PASS responses */
 static CURLcode ftp_state_user_resp(struct Curl_easy *data,
-                                    int ftpcode,
-                                    ftpstate instate)
+                                    int ftpcode)
 {
   CURLcode result = CURLE_OK;
   struct connectdata *conn = data->conn;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
-  (void)instate; /* no use for this yet */
 
   /* some need password anyway, and others just return 2xx ignored */
   if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
@@ -2655,7 +2653,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
         /* 230 User logged in - already! Take as 220 if TLS required. */
         if(data->set.use_ssl <= CURLUSESSL_TRY ||
            conn->bits.ftp_use_control_ssl)
-          return ftp_state_user_resp(data, ftpcode, ftpc->state);
+          return ftp_state_user_resp(data, ftpcode);
       }
       else if(ftpcode != 220) {
         failf(data, "Got a %03d ftp-server response when 220 was expected",
@@ -2760,7 +2758,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
 
     case FTP_USER:
     case FTP_PASS:
-      result = ftp_state_user_resp(data, ftpcode, ftpc->state);
+      result = ftp_state_user_resp(data, ftpcode);
       break;
 
     case FTP_ACCT:

+ 25 - 24
lib/ftp.h

@@ -42,7 +42,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data, ssize_t *nread,
 /****************************************************************************
  * FTP unique setup
  ***************************************************************************/
-typedef enum {
+enum {
   FTP_STOP,    /* do nothing state, stops the state machine */
   FTP_WAIT220, /* waiting for the initial 220 response immediately after
                   a connect */
@@ -80,7 +80,8 @@ typedef enum {
   FTP_STOR, /* generic state for STOR and APPE */
   FTP_QUIT,
   FTP_LAST  /* never used */
-} ftpstate;
+};
+typedef unsigned char ftpstate; /* use the enum values */
 
 struct ftp_parselist_data; /* defined later in ftplistparser.c */
 
@@ -122,38 +123,38 @@ struct ftp_conn {
   char *entrypath; /* the PWD reply when we logged on */
   char *file;    /* url-decoded file name (or path) */
   char **dirs;   /* realloc()ed array for path components */
-  int dirdepth;  /* number of entries used in the 'dirs' array */
-  bool dont_check;  /* Set to TRUE to prevent the final (post-transfer)
-                       file size and 226/250 status check. It should still
-                       read the line, just ignore the result. */
-  bool ctl_valid;   /* Tells Curl_ftp_quit() whether or not to do anything. If
-                       the connection has timed out or been closed, this
-                       should be FALSE when it gets to Curl_ftp_quit() */
-  bool cwddone;     /* if it has been determined that the proper CWD combo
-                       already has been done */
-  int cwdcount;     /* number of CWD commands issued */
-  bool cwdfail;     /* set TRUE if a CWD command fails, as then we must prevent
-                       caching the current directory */
-  bool wait_data_conn; /* this is set TRUE if data connection is waited */
-  /* newhost is the (allocated) IP addr or host name to connect the data
-     connection to */
-  unsigned short newport;
   char *newhost;
   char *prevpath;   /* url-decoded conn->path from the previous transfer */
   char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
                         and others (A/I or zero) */
-  int count1; /* general purpose counter for the state machine */
-  int count2; /* general purpose counter for the state machine */
-  int count3; /* general purpose counter for the state machine */
-  ftpstate state; /* always use ftp.c:state() to change state! */
-  ftpstate state_saved; /* transfer type saved to be reloaded after
-                           data connection is established */
   curl_off_t retr_size_saved; /* Size of retrieved file saved */
   char *server_os;     /* The target server operating system. */
   curl_off_t known_filesize; /* file size is different from -1, if wildcard
                                 LIST parsing was done and wc_statemach set
                                 it */
+  int dirdepth;  /* number of entries used in the 'dirs' array */
+  int cwdcount;     /* number of CWD commands issued */
+  int count1; /* general purpose counter for the state machine */
+  int count2; /* general purpose counter for the state machine */
+  int count3; /* general purpose counter for the state machine */
+  /* newhost is the (allocated) IP addr or host name to connect the data
+     connection to */
+  unsigned short newport;
+  ftpstate state; /* always use ftp.c:state() to change state! */
+  ftpstate state_saved; /* transfer type saved to be reloaded after data
+                           connection is established */
   BIT(ftp_trying_alternative);
+  BIT(dont_check);  /* Set to TRUE to prevent the final (post-transfer)
+                       file size and 226/250 status check. It should still
+                       read the line, just ignore the result. */
+  BIT(ctl_valid);   /* Tells Curl_ftp_quit() whether or not to do anything. If
+                       the connection has timed out or been closed, this
+                       should be FALSE when it gets to Curl_ftp_quit() */
+  BIT(cwddone);     /* if it has been determined that the proper CWD combo
+                       already has been done */
+  BIT(cwdfail);     /* set TRUE if a CWD command fails, as then we must prevent
+                       caching the current directory */
+  BIT(wait_data_conn); /* this is set TRUE if data connection is waited */
 };
 
 #define DEFAULT_ACCEPT_TIMEOUT   60000 /* milliseconds == one minute */

+ 8 - 4
lib/imap.c

@@ -475,6 +475,7 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
   /* Start the SSL connection */
   struct imap_conn *imapc = &conn->proto.imapc;
   CURLcode result;
+  bool ssldone = FALSE;
 
   if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
     result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
@@ -482,8 +483,9 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
       goto out;
   }
 
-  result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &imapc->ssldone);
+  result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
   if(!result) {
+    imapc->ssldone = ssldone;
     if(imapc->state != IMAP_UPGRADETLS)
       state(data, IMAP_UPGRADETLS);
 
@@ -1386,8 +1388,10 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
   struct imap_conn *imapc = &conn->proto.imapc;
 
   if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
-    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &imapc->ssldone);
-    if(result || !imapc->ssldone)
+    bool ssldone = FALSE;
+    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
+    imapc->ssldone = ssldone;
+    if(result || !ssldone)
       return result;
   }
 
@@ -1774,7 +1778,7 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
   /* Calculate the tag based on the connection ID and command ID */
   msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
             'A' + curlx_sltosi(data->conn->connection_id % 26),
-            (++imapc->cmdid)%1000);
+            ++imapc->cmdid);
 
   /* start with a blank buffer */
   Curl_dyn_reset(&imapc->dyn);

+ 11 - 11
lib/imap.h

@@ -72,19 +72,19 @@ struct IMAP {
    struct */
 struct imap_conn {
   struct pingpong pp;
-  imapstate state;            /* Always use imap.c:state() to change state! */
-  bool ssldone;               /* Is connect() over SSL done? */
-  bool preauth;               /* Is this connection PREAUTH? */
   struct SASL sasl;           /* SASL-related parameters */
-  unsigned int preftype;      /* Preferred authentication type */
-  unsigned int cmdid;         /* Last used command ID */
-  char resptag[5];            /* Response tag to wait for */
-  bool tls_supported;         /* StartTLS capability supported by server */
-  bool login_disabled;        /* LOGIN command disabled by server */
-  bool ir_supported;          /* Initial response supported by server */
+  struct dynbuf dyn;          /* for the IMAP commands */
   char *mailbox;              /* The last selected mailbox */
   char *mailbox_uidvalidity;  /* UIDVALIDITY parsed from select response */
-  struct dynbuf dyn;          /* for the IMAP commands */
+  imapstate state;            /* Always use imap.c:state() to change state! */
+  char resptag[5];            /* Response tag to wait for */
+  unsigned char preftype;     /* Preferred authentication type */
+  unsigned char cmdid;        /* Last used command ID */
+  BIT(ssldone);               /* Is connect() over SSL done? */
+  BIT(preauth);               /* Is this connection PREAUTH? */
+  BIT(tls_supported);         /* StartTLS capability supported by server */
+  BIT(login_disabled);        /* LOGIN command disabled by server */
+  BIT(ir_supported);          /* Initial response supported by server */
 };
 
 extern const struct Curl_handler Curl_handler_imap;
@@ -96,6 +96,6 @@ extern const struct Curl_handler Curl_handler_imaps;
 
 /* Authentication type values */
 #define IMAP_TYPE_NONE      0
-#define IMAP_TYPE_ANY       ~0U
+#define IMAP_TYPE_ANY       (IMAP_TYPE_CLEARTEXT|IMAP_TYPE_SASL)
 
 #endif /* HEADER_CURL_IMAP_H */

+ 6 - 2
lib/pop3.c

@@ -370,6 +370,7 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
   /* Start the SSL connection */
   struct pop3_conn *pop3c = &conn->proto.pop3c;
   CURLcode result;
+  bool ssldone = FALSE;
 
   if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
     result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
@@ -377,9 +378,10 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
       goto out;
   }
 
-  result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &pop3c->ssldone);
+  result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
 
   if(!result) {
+    pop3c->ssldone = ssldone;
     if(pop3c->state != POP3_UPGRADETLS)
       state(data, POP3_UPGRADETLS);
 
@@ -1056,7 +1058,9 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
   struct pop3_conn *pop3c = &conn->proto.pop3c;
 
   if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
-    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &pop3c->ssldone);
+    bool ssldone = FALSE;
+    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
+    pop3c->ssldone = ssldone;
     if(result || !pop3c->ssldone)
       return result;
   }

+ 5 - 5
lib/pop3.h

@@ -62,16 +62,16 @@ struct POP3 {
 struct pop3_conn {
   struct pingpong pp;
   pop3state state;        /* Always use pop3.c:state() to change state! */
-  bool ssldone;           /* Is connect() over SSL done? */
-  bool tls_supported;     /* StartTLS capability supported by server */
   size_t eob;             /* Number of bytes of the EOB (End Of Body) that
                              have been received so far */
   size_t strip;           /* Number of bytes from the start to ignore as
                              non-body */
   struct SASL sasl;       /* SASL-related storage */
-  unsigned int authtypes; /* Accepted authentication types */
-  unsigned int preftype;  /* Preferred authentication type */
   char *apoptimestamp;    /* APOP timestamp from the server greeting */
+  unsigned char authtypes; /* Accepted authentication types */
+  unsigned char preftype;  /* Preferred authentication type */
+  BIT(ssldone);           /* Is connect() over SSL done? */
+  BIT(tls_supported);     /* StartTLS capability supported by server */
 };
 
 extern const struct Curl_handler Curl_handler_pop3;
@@ -84,7 +84,7 @@ extern const struct Curl_handler Curl_handler_pop3s;
 
 /* Authentication type values */
 #define POP3_TYPE_NONE      0
-#define POP3_TYPE_ANY       ~0U
+#define POP3_TYPE_ANY       (POP3_TYPE_CLEARTEXT|POP3_TYPE_APOP|POP3_TYPE_SASL)
 
 /* This is the 5-bytes End-Of-Body marker for POP3 */
 #define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"

+ 2 - 2
lib/setopt.c

@@ -463,8 +463,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
          version_max >= CURL_SSLVERSION_MAX_LAST)
         return CURLE_BAD_FUNCTION_ARGUMENT;
 
-      primary->version = version;
-      primary->version_max = version_max;
+      primary->version = (unsigned char)version;
+      primary->version_max = (unsigned int)version_max;
     }
 #else
     result = CURLE_NOT_BUILT_IN;

+ 6 - 2
lib/smtp.c

@@ -398,6 +398,7 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
   struct connectdata *conn = data->conn;
   struct smtp_conn *smtpc = &conn->proto.smtpc;
   CURLcode result;
+  bool ssldone = FALSE;
 
   if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
     result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
@@ -405,8 +406,9 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
       goto out;
   }
 
-  result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &smtpc->ssldone);
+  result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
   if(!result) {
+    smtpc->ssldone = ssldone;
     if(smtpc->state != SMTP_UPGRADETLS)
       state(data, SMTP_UPGRADETLS);
 
@@ -1288,7 +1290,9 @@ static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done)
   struct smtp_conn *smtpc = &conn->proto.smtpc;
 
   if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
-    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &smtpc->ssldone);
+    bool ssldone = FALSE;
+    result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
+    smtpc->ssldone = ssldone;
     if(result || !smtpc->ssldone)
       return result;
   }

+ 9 - 9
lib/smtp.h

@@ -57,28 +57,28 @@ struct SMTP {
   curl_pp_transfer transfer;
   char *custom;            /* Custom Request */
   struct curl_slist *rcpt; /* Recipient list */
-  bool rcpt_had_ok;        /* Whether any of RCPT TO commands (depends on
-                              total number of recipients) succeeded so far */
-  bool trailing_crlf;      /* Specifies if the trailing CRLF is present */
   int rcpt_last_error;     /* The last error received for RCPT TO command */
   size_t eob;              /* Number of bytes of the EOB (End Of Body) that
                               have been received so far */
+  BIT(rcpt_had_ok);        /* Whether any of RCPT TO commands (depends on
+                              total number of recipients) succeeded so far */
+  BIT(trailing_crlf);      /* Specifies if the trailing CRLF is present */
 };
 
 /* smtp_conn is used for struct connection-oriented data in the connectdata
    struct */
 struct smtp_conn {
   struct pingpong pp;
+  struct SASL sasl;        /* SASL-related storage */
   smtpstate state;         /* Always use smtp.c:state() to change state! */
-  bool ssldone;            /* Is connect() over SSL done? */
   char *domain;            /* Client address/name to send in the EHLO */
-  struct SASL sasl;        /* SASL-related storage */
-  bool tls_supported;      /* StartTLS capability supported by server */
-  bool size_supported;     /* If server supports SIZE extension according to
+  BIT(ssldone);            /* Is connect() over SSL done? */
+  BIT(tls_supported);      /* StartTLS capability supported by server */
+  BIT(size_supported);     /* If server supports SIZE extension according to
                               RFC 1870 */
-  bool utf8_supported;     /* If server supports SMTPUTF8 extension according
+  BIT(utf8_supported);     /* If server supports SMTPUTF8 extension according
                               to RFC 6531 */
-  bool auth_supported;     /* AUTH capability supported by server */
+  BIT(auth_supported);     /* AUTH capability supported by server */
 };
 
 extern const struct Curl_handler Curl_handler_smtp;

+ 2 - 2
lib/urldata.h

@@ -267,8 +267,6 @@ typedef enum {
 struct ssl_backend_data;
 
 struct ssl_primary_config {
-  long version;          /* what version the client wants to use */
-  long version_max;      /* max supported version the client wants to use */
   char *CApath;          /* certificate dir (doesn't work on windows) */
   char *CAfile;          /* certificate to verify peer against */
   char *issuercert;      /* optional issuer certificate filename */
@@ -286,6 +284,8 @@ struct ssl_primary_config {
 #endif
   char *curves;          /* list of curves to use */
   unsigned char ssl_options;  /* the CURLOPT_SSL_OPTIONS bitmask */
+  unsigned int version_max; /* max supported version the client wants to use */
+  unsigned char version;    /* what version the client wants to use */
   BIT(verifypeer);       /* set TRUE if this is desired */
   BIT(verifyhost);       /* set TRUE if CN/SAN must match hostname */
   BIT(verifystatus);     /* set TRUE if certificate status must be checked */

+ 2 - 2
lib/vtls/vtls.c

@@ -268,8 +268,8 @@ void Curl_ssl_cleanup(void)
 static bool ssl_prefs_check(struct Curl_easy *data)
 {
   /* check for CURLOPT_SSLVERSION invalid parameter value */
-  const long sslver = data->set.ssl.primary.version;
-  if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) {
+  const unsigned char sslver = data->set.ssl.primary.version;
+  if(sslver >= CURL_SSLVERSION_LAST) {
     failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
     return FALSE;
   }