Instead of a bare recv() to read the server's response to an SSL
authorTom Lane
Thu, 6 Jan 2005 20:06:58 +0000 (20:06 +0000)
committerTom Lane
Thu, 6 Jan 2005 20:06:58 +0000 (20:06 +0000)
request packet, use pqReadData().  This has the same effect since
conn->ssl isn't set yet and we aren't expecting more than one byte.
The advantage is that we will correctly detect loss-of-connection
instead of going into an infinite loop.  Per report from Hannu Krosing.

src/interfaces/libpq/fe-connect.c

index 908c39c25671fcab90232ccd5421c43a54c689e1..2949cf64a38de56d4b9c0d2b87860d46476f810e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.297 2005/01/06 18:29:10 tgl Exp $
+ *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.298 2005/01/06 20:06:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1452,30 +1452,36 @@ keep_going:                     /* We will come back to here until there
 
                /*
                 * On first time through, get the postmaster's response to
-                * our SSL negotiation packet.  Be careful to read only
-                * one byte (if there's more, it could be SSL data).
+                * our SSL negotiation packet.
                 */
                if (conn->ssl == NULL)
                {
+                   /*
+                    * We use pqReadData here since it has the logic to
+                    * distinguish no-data-yet from connection closure.
+                    * Since conn->ssl isn't set, a plain recv() will occur.
+                    */
                    char        SSLok;
-                   int         nread;
+                   int         rdresult;
 
-           retry_ssl_read:
-                   nread = recv(conn->sock, &SSLok, 1, 0);
-                   if (nread < 0)
+                   rdresult = pqReadData(conn);
+                   if (rdresult < 0)
                    {
-                       if (SOCK_ERRNO == EINTR)
-                           /* Interrupted system call - just try again */
-                           goto retry_ssl_read;
-
-                       printfPQExpBuffer(&conn->errorMessage,
-                                         libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
-                       SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+                       /* errorMessage is already filled in */
                        goto error_return;
                    }
-                   if (nread == 0)
+                   if (rdresult == 0)
+                   {
                        /* caller failed to wait for data */
                        return PGRES_POLLING_READING;
+                   }
+                   if (pqGetc(&SSLok, conn) < 0)
+                   {
+                       /* should not happen really */
+                       return PGRES_POLLING_READING;
+                   }
+                   /* mark byte consumed */
+                   conn->inStart = conn->inCursor;
                    if (SSLok == 'S')
                    {
                        /* Do one-time setup; this creates conn->ssl */