ginbuf.value = NULL;
}
+ /* finished parsing, trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
/* Only try to acquire credentials if GSS delegation isn't disabled. */
if (!pg_GSS_have_cred_cache(&conn->gcred))
conn->gcred = GSS_C_NO_CREDENTIAL;
InBuffers[0].BufferType = SECBUFFER_TOKEN;
}
+ /* finished parsing, trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].cbBuffer = 0;
}
}
+ /* finished parsing, trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
Assert(conn->sasl);
/*
free(challenge);
return STATUS_ERROR;
}
+
+ /* finished parsing, trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
/* For safety and convenience, ensure the buffer is NULL-terminated. */
challenge[payloadlen] = '\0';
return STATUS_ERROR; /* shouldn't happen */
}
+ /* finished parsing, trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
/* Encrypt the password if needed. */
switch (areq)
return PGRES_POLLING_READING;
}
/* OK, we read the message; mark data consumed */
- conn->inStart = conn->inCursor;
+ pqParseDone(conn, conn->inCursor);
/*
* Before 7.2, the postmaster didn't always end its
goto error_return;
}
/* OK, we read the message; mark data consumed */
- conn->inStart = conn->inCursor;
+ pqParseDone(conn, conn->inCursor);
/*
* If error is "cannot connect now", try the next host if
goto error_return;
}
/* OK, we read the message; mark data consumed */
- conn->inStart = conn->inCursor;
+ pqParseDone(conn, conn->inCursor);
goto error_return;
}
*/
res = pg_fe_sendauth(areq, msgLength, conn);
- /* OK, we have processed the message; mark data consumed */
+ /*
+ * OK, we have processed the message; mark data consumed. We
+ * don't call pqParseDone here because we already traced this
+ * message inside pg_fe_sendauth.
+ */
conn->inStart = conn->inCursor;
if (res != STATUS_OK)
return EOF;
}
+/*
+ * pqParseDone: after a server-to-client message has successfully
+ * been parsed, advance conn->inStart to account for it.
+ */
+void
+pqParseDone(PGconn *conn, int newInStart)
+{
+ /* trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
+ /* Mark message as done */
+ conn->inStart = newInStart;
+}
+
/*
* pqPutMsgStart: begin construction of a message to the server
*
/* Successfully consumed this message */
if (conn->inCursor == conn->inStart + 5 + msgLength)
{
- /* trace server-to-client message */
- if (conn->Pfdebug)
- pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
-
/* Normal case: parsing agrees with specified length */
- conn->inStart = conn->inCursor;
+ pqParseDone(conn, conn->inCursor);
}
else
{
return -1;
}
- /* trace server-to-client message */
- if (conn->Pfdebug)
- pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
-
/* Drop the processed message and loop around for another */
- conn->inStart = conn->inCursor;
+ pqParseDone(conn, conn->inCursor);
}
}
(*buffer)[msgLength] = '\0'; /* Add terminating null */
/* Mark message consumed */
- conn->inStart = conn->inCursor + msgLength;
+ pqParseDone(conn, conn->inCursor + msgLength);
return msgLength;
}
/* Empty, so drop it and loop around for another */
- conn->inStart = conn->inCursor;
+ pqParseDone(conn, conn->inCursor);
}
}
case 'Z': /* backend is ready for new query */
if (getReadyForQuery(conn))
continue;
- /* consume the message and exit */
- conn->inStart += 5 + msgLength;
+
+ /* consume the message */
+ pqParseDone(conn, conn->inStart + 5 + msgLength);
/*
* If we already have a result object (probably an error), use
pqSaveErrorResult(conn);
}
}
+ /* and we're out */
return pqPrepareAsyncResult(conn);
case 'S': /* parameter status */
if (getParameterStatus(conn))
/* The backend violates the protocol. */
libpq_append_conn_error(conn, "protocol error: id=0x%x", id);
pqSaveErrorResult(conn);
- /* trust the specified message length as what to skip */
+
+ /*
+ * We can't call parsing done due to the protocol violation
+ * (so message tracing wouldn't work), but trust the specified
+ * message length as what to skip.
+ */
conn->inStart += 5 + msgLength;
return pqPrepareAsyncResult(conn);
}
- /* trace server-to-client message */
- if (conn->Pfdebug)
- pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
-
- /* Completed this message, keep going */
- /* trust the specified message length as what to skip */
- conn->inStart += 5 + msgLength;
+ /* Completed parsing this message, keep going */
+ pqParseDone(conn, conn->inStart + 5 + msgLength);
needInput = false;
}
pqTraceOutputString(f, message, cursor, false);
}
+static void
+pqTraceOutput_CopyData(FILE *f, const char *message, int *cursor, int length,
+ bool suppress)
+{
+ fprintf(f, "CopyData\t");
+ pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, suppress);
+}
+
static void
pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor)
{
}
static void
-pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor)
+pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor,
+ int length, bool suppress)
{
- fprintf(f, "Authentication\t");
- pqTraceOutputInt32(f, message, cursor, false);
+ int authType = 0;
+
+ memcpy(&authType, message + *cursor, 4);
+ authType = (int) pg_ntoh32(authType);
+ *cursor += 4;
+ switch (authType)
+ {
+ case AUTH_REQ_OK:
+ fprintf(f, "AuthenticationOk");
+ break;
+ /* AUTH_REQ_KRB4 not supported */
+ /* AUTH_REQ_KRB5 not supported */
+ case AUTH_REQ_PASSWORD:
+ fprintf(f, "AuthenticationCleartextPassword");
+ break;
+ /* AUTH_REQ_CRYPT not supported */
+ case AUTH_REQ_MD5:
+ fprintf(f, "AuthenticationMD5Password");
+ break;
+ case AUTH_REQ_GSS:
+ fprintf(f, "AuthenticationGSS");
+ break;
+ case AUTH_REQ_GSS_CONT:
+ fprintf(f, "AuthenticationGSSContinue\t");
+ pqTraceOutputNchar(f, length - *cursor + 1, message, cursor,
+ suppress);
+ break;
+ case AUTH_REQ_SSPI:
+ fprintf(f, "AuthenticationSSPI");
+ break;
+ case AUTH_REQ_SASL:
+ fprintf(f, "AuthenticationSASL\t");
+ while (message[*cursor] != '\0')
+ pqTraceOutputString(f, message, cursor, false);
+ pqTraceOutputString(f, message, cursor, false);
+ break;
+ case AUTH_REQ_SASL_CONT:
+ fprintf(f, "AuthenticationSASLContinue\t");
+ pqTraceOutputNchar(f, length - *cursor + 1, message, cursor,
+ suppress);
+ break;
+ case AUTH_REQ_SASL_FIN:
+ fprintf(f, "AuthenticationSASLFinal\t");
+ pqTraceOutputNchar(f, length - *cursor + 1, message, cursor,
+ suppress);
+ break;
+ default:
+ fprintf(f, "Unknown authentication message %d", authType);
+ }
}
static void
pqTraceOutput_CommandComplete(conn->Pfdebug, message, &logCursor);
break;
case PqMsg_CopyData:
- /* Drop COPY data to reduce the overhead of logging. */
+ pqTraceOutput_CopyData(conn->Pfdebug, message, &logCursor,
+ length, regress);
break;
case PqMsg_Describe:
/* Describe(F) and DataRow(B) use the same identifier. */
pqTraceOutput_Query(conn->Pfdebug, message, &logCursor);
break;
case PqMsg_AuthenticationRequest:
- pqTraceOutput_Authentication(conn->Pfdebug, message, &logCursor);
+ pqTraceOutput_Authentication(conn->Pfdebug, message, &logCursor,
+ length, regress);
break;
case PqMsg_PortalSuspended:
fprintf(conn->Pfdebug, "PortalSuspended");
*/
extern int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn);
extern int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn);
+extern void pqParseDone(PGconn *conn, int newInStart);
extern int pqGetc(char *result, PGconn *conn);
extern int pqPutc(char c, PGconn *conn);
extern int pqGets(PQExpBuffer buf, PGconn *conn);