aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-misc.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-06-08 17:43:00 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-06-08 17:43:00 +0000
commit6bdb7aa4db5571c83c87f5f761d4af4bc73e166e (patch)
treebf819a9fe25640b32f9899d0bf41b218df8d2d98 /src/interfaces/libpq/fe-misc.c
parent152ce7a4909aec35771e925fd7fa97bae1103763 (diff)
downloadpostgresql-6bdb7aa4db5571c83c87f5f761d4af4bc73e166e.tar.gz
postgresql-6bdb7aa4db5571c83c87f5f761d4af4bc73e166e.zip
libpq can now talk to either 3.0 or 2.0 protocol servers. It first tries
protocol 3, then falls back to 2 if postmaster rejects the startup packet with an old-format error message. A side benefit of the rewrite is that SSL-encrypted connections can now be made without blocking. (I think, anyway, but do not have a good way to test.)
Diffstat (limited to 'src/interfaces/libpq/fe-misc.c')
-rw-r--r--src/interfaces/libpq/fe-misc.c71
1 files changed, 47 insertions, 24 deletions
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index 042ef204aba..80c1c5a7891 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -23,7 +23,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.91 2003/04/25 01:24:00 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.92 2003/06/08 17:43:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,8 +58,6 @@
#include "pqsignal.h"
#include "mb/pg_wchar.h"
-#define DONOTICE(conn,message) \
- ((*(conn)->noticeHook) ((conn)->noticeArg, (message)))
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn);
static int pqSendSome(PGconn *conn, int len);
@@ -227,7 +225,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
snprintf(noticeBuf, sizeof(noticeBuf),
libpq_gettext("integer of size %lu not supported by pqGetInt\n"),
(unsigned long) bytes);
- DONOTICE(conn, noticeBuf);
+ PGDONOTICE(conn, noticeBuf);
return EOF;
}
@@ -265,7 +263,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
snprintf(noticeBuf, sizeof(noticeBuf),
libpq_gettext("integer of size %lu not supported by pqPutInt\n"),
(unsigned long) bytes);
- DONOTICE(conn, noticeBuf);
+ PGDONOTICE(conn, noticeBuf);
return EOF;
}
@@ -401,38 +399,57 @@ pqCheckInBufferSpace(int bytes_needed, PGconn *conn)
* msg_type is the message type byte, or 0 for a message without type byte
* (only startup messages have no type byte)
*
+ * force_len forces the message to have a length word; otherwise, we add
+ * a length word if protocol 3.
+ *
* Returns 0 on success, EOF on error
*
* The idea here is that we construct the message in conn->outBuffer,
* beginning just past any data already in outBuffer (ie, at
* outBuffer+outCount). We enlarge the buffer as needed to hold the message.
- * When the message is complete, we fill in the length word and then advance
- * outCount past the message, making it eligible to send. The state
- * variable conn->outMsgStart points to the incomplete message's length word
- * (it is either outCount or outCount+1 depending on whether there is a
- * type byte). The state variable conn->outMsgEnd is the end of the data
- * collected so far.
+ * When the message is complete, we fill in the length word (if needed) and
+ * then advance outCount past the message, making it eligible to send.
+ *
+ * The state variable conn->outMsgStart points to the incomplete message's
+ * length word: it is either outCount or outCount+1 depending on whether
+ * there is a type byte. If we are sending a message without length word
+ * (pre protocol 3.0 only), then outMsgStart is -1. The state variable
+ * conn->outMsgEnd is the end of the data collected so far.
*/
int
-pqPutMsgStart(char msg_type, PGconn *conn)
+pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
{
int lenPos;
+ int endPos;
- /* where the message length word will go */
+ /* allow room for message type byte */
if (msg_type)
- lenPos = conn->outCount + 1;
+ endPos = conn->outCount + 1;
else
- lenPos = conn->outCount;
- /* make sure there is room for it */
- if (pqCheckOutBufferSpace(lenPos + 4, conn))
+ endPos = conn->outCount;
+
+ /* do we want a length word? */
+ if (force_len || PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+ {
+ lenPos = endPos;
+ /* allow room for message length */
+ endPos += 4;
+ }
+ else
+ {
+ lenPos = -1;
+ }
+
+ /* make sure there is room for message header */
+ if (pqCheckOutBufferSpace(endPos, conn))
return EOF;
/* okay, save the message type byte if any */
if (msg_type)
conn->outBuffer[conn->outCount] = msg_type;
/* set up the message pointers */
conn->outMsgStart = lenPos;
- conn->outMsgEnd = lenPos + 4;
- /* length word will be filled in by pqPutMsgEnd */
+ conn->outMsgEnd = endPos;
+ /* length word, if needed, will be filled in by pqPutMsgEnd */
if (conn->Pfdebug)
fprintf(conn->Pfdebug, "To backend> Msg %c\n",
@@ -472,14 +489,20 @@ pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
int
pqPutMsgEnd(PGconn *conn)
{
- uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
-
if (conn->Pfdebug)
fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
- msgLen);
+ conn->outMsgEnd - conn->outCount);
+
+ /* Fill in length word if needed */
+ if (conn->outMsgStart >= 0)
+ {
+ uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
+
+ msgLen = htonl(msgLen);
+ memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
+ }
- msgLen = htonl(msgLen);
- memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
+ /* Make message eligible to send */
conn->outCount = conn->outMsgEnd;
if (conn->outCount >= 8192)