aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/pqpacket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/pqpacket.c')
-rw-r--r--src/backend/libpq/pqpacket.c361
1 files changed, 192 insertions, 169 deletions
diff --git a/src/backend/libpq/pqpacket.c b/src/backend/libpq/pqpacket.c
index 6f67ddc5f5b..9f56556537f 100644
--- a/src/backend/libpq/pqpacket.c
+++ b/src/backend/libpq/pqpacket.c
@@ -1,39 +1,39 @@
/*-------------------------------------------------------------------------
*
* pqpacket.c--
- * routines for reading and writing data packets sent/received by
- * POSTGRES clients and servers
+ * routines for reading and writing data packets sent/received by
+ * POSTGRES clients and servers
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.5 1997/08/12 22:53:00 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.6 1997/09/07 04:42:28 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/* NOTES
- * This is the module that understands the lowest-level part
- * of the communication protocol. All of the trickiness in
- * this module is for making sure that non-blocking I/O in
- * the Postmaster works correctly. Check the notes in PacketRecv
- * on non-blocking I/O.
+ * This is the module that understands the lowest-level part
+ * of the communication protocol. All of the trickiness in
+ * this module is for making sure that non-blocking I/O in
+ * the Postmaster works correctly. Check the notes in PacketRecv
+ * on non-blocking I/O.
*
* Data Structures:
- * Port has two important functions. (1) It records the
- * sock/addr used in communication. (2) It holds partially
- * read in messages. This is especially important when
- * we haven't seen enough to construct a complete packet
- * header.
+ * Port has two important functions. (1) It records the
+ * sock/addr used in communication. (2) It holds partially
+ * read in messages. This is especially important when
+ * we haven't seen enough to construct a complete packet
+ * header.
*
* PacketBuf -- None of the clients of this module should know
- * what goes into a packet hdr (although they know how big
- * it is). This routine is in charge of host to net order
- * conversion for headers. Data conversion is someone elses
- * responsibility.
+ * what goes into a packet hdr (although they know how big
+ * it is). This routine is in charge of host to net order
+ * conversion for headers. Data conversion is someone elses
+ * responsibility.
*
* IMPORTANT: these routines are called by backends, clients, and
- * the Postmaster.
+ * the Postmaster.
*
*/
#include <stdio.h>
@@ -57,134 +57,156 @@
*
*/
int
-PacketReceive(Port *port, /* receive port */
- PacketBuf *buf, /* MAX_PACKET_SIZE-worth of buffer space */
- bool nonBlocking) /* NON_BLOCKING or BLOCKING i/o */
+PacketReceive(Port * port, /* receive port */
+ PacketBuf * buf, /* MAX_PACKET_SIZE-worth of buffer space */
+ bool nonBlocking) /* NON_BLOCKING or BLOCKING i/o */
{
- PacketLen max_size = sizeof(PacketBuf);
- PacketLen cc; /* character count -- bytes recvd */
- PacketLen packetLen; /* remaining packet chars to read */
- Addr tmp; /* curr recv buf pointer */
- int addrLen = sizeof(struct sockaddr_in);
- int hdrLen;
- int flag;
- int decr;
-
- hdrLen = sizeof(buf->len);
-
- if (nonBlocking == NON_BLOCKING) {
- flag = MSG_PEEK;
- decr = 0;
- } else {
- flag = 0;
- decr = hdrLen;
- }
- /*
- * Assume port->nBytes is zero unless we were interrupted during
- * non-blocking I/O. This first recvfrom() is to get the hdr
- * information so we know how many bytes to read. Life would
- * be very complicated if we read too much data (buffering).
- */
- tmp = ((Addr)buf) + port->nBytes;
-
- if (port->nBytes >= hdrLen) {
- packetLen = ntohl(buf->len) - port->nBytes;
- }
- else {
- /* peeking into the incoming message */
- cc = recvfrom(port->sock, (char *)&(buf->len), hdrLen, flag,
- (struct sockaddr*) &(port->raddr), &addrLen);
- if (cc < hdrLen) {
- /* if cc is negative, the system call failed */
- if (cc < 0) {
- return(STATUS_ERROR);
- }
- /*
- * cc == 0 means the connection was broken at the
- * other end.
- */
- else if (! cc) {
- return(STATUS_INVALID);
-
- } else {
- /*
- * Worst case. We didn't even read in enough data to
- * get the header length.
- * since we are using a data stream,
- * this happens only if the client is mallicious.
- *
- * Don't save the number of bytes we've read so far.
- * Since we only peeked at the incoming message, the
- * kernel is going to keep it for us.
- */
- return(STATUS_NOT_DONE);
- }
- } else {
- /*
- * This is an attempt to shield the Postmaster
- * from mallicious attacks by placing tighter
- * restrictions on the reported packet length.
- *
- * Check for negative packet length
- */
- if ((buf->len) <= 0) {
- return(STATUS_INVALID);
- }
- /*
- * Check for oversize packet
- */
- if ((ntohl(buf->len)) > max_size) {
- return(STATUS_INVALID);
- }
- /*
- * great. got the header. now get the true length (including
- * header size).
- */
- packetLen = ntohl(buf->len);
- /*
- * if someone is sending us junk, close the connection
- */
- if (packetLen > max_size) {
- port->nBytes = packetLen;
- return(STATUS_BAD_PACKET);
- }
- packetLen -= decr;
- tmp += decr - port->nBytes;
+ PacketLen max_size = sizeof(PacketBuf);
+ PacketLen cc; /* character count -- bytes recvd */
+ PacketLen packetLen; /* remaining packet chars to read */
+ Addr tmp; /* curr recv buf pointer */
+ int addrLen = sizeof(struct sockaddr_in);
+ int hdrLen;
+ int flag;
+ int decr;
+
+ hdrLen = sizeof(buf->len);
+
+ if (nonBlocking == NON_BLOCKING)
+ {
+ flag = MSG_PEEK;
+ decr = 0;
+ }
+ else
+ {
+ flag = 0;
+ decr = hdrLen;
+ }
+
+ /*
+ * Assume port->nBytes is zero unless we were interrupted during
+ * non-blocking I/O. This first recvfrom() is to get the hdr
+ * information so we know how many bytes to read. Life would be very
+ * complicated if we read too much data (buffering).
+ */
+ tmp = ((Addr) buf) + port->nBytes;
+
+ if (port->nBytes >= hdrLen)
+ {
+ packetLen = ntohl(buf->len) - port->nBytes;
+ }
+ else
+ {
+ /* peeking into the incoming message */
+ cc = recvfrom(port->sock, (char *) &(buf->len), hdrLen, flag,
+ (struct sockaddr *) & (port->raddr), &addrLen);
+ if (cc < hdrLen)
+ {
+ /* if cc is negative, the system call failed */
+ if (cc < 0)
+ {
+ return (STATUS_ERROR);
+ }
+
+ /*
+ * cc == 0 means the connection was broken at the other end.
+ */
+ else if (!cc)
+ {
+ return (STATUS_INVALID);
+
+ }
+ else
+ {
+
+ /*
+ * Worst case. We didn't even read in enough data to get
+ * the header length. since we are using a data stream,
+ * this happens only if the client is mallicious.
+ *
+ * Don't save the number of bytes we've read so far. Since we
+ * only peeked at the incoming message, the kernel is
+ * going to keep it for us.
+ */
+ return (STATUS_NOT_DONE);
+ }
+ }
+ else
+ {
+
+ /*
+ * This is an attempt to shield the Postmaster from mallicious
+ * attacks by placing tighter restrictions on the reported
+ * packet length.
+ *
+ * Check for negative packet length
+ */
+ if ((buf->len) <= 0)
+ {
+ return (STATUS_INVALID);
+ }
+
+ /*
+ * Check for oversize packet
+ */
+ if ((ntohl(buf->len)) > max_size)
+ {
+ return (STATUS_INVALID);
+ }
+
+ /*
+ * great. got the header. now get the true length (including
+ * header size).
+ */
+ packetLen = ntohl(buf->len);
+
+ /*
+ * if someone is sending us junk, close the connection
+ */
+ if (packetLen > max_size)
+ {
+ port->nBytes = packetLen;
+ return (STATUS_BAD_PACKET);
+ }
+ packetLen -= decr;
+ tmp += decr - port->nBytes;
+ }
}
- }
-
- /*
- * Now that we know how big it is, read the packet. We read
- * the entire packet, since the last call was just a peek.
- */
- while (packetLen) {
- cc = recvfrom(port->sock, tmp, packetLen, 0,
- (struct sockaddr*) &(port->raddr), &addrLen);
- if (cc < 0)
- return(STATUS_ERROR);
- /*
- * cc == 0 means the connection was broken at the
- * other end.
+
+ /*
+ * Now that we know how big it is, read the packet. We read the
+ * entire packet, since the last call was just a peek.
*/
- else if (! cc)
- return(STATUS_INVALID);
-
+ while (packetLen)
+ {
+ cc = recvfrom(port->sock, tmp, packetLen, 0,
+ (struct sockaddr *) & (port->raddr), &addrLen);
+ if (cc < 0)
+ return (STATUS_ERROR);
+
+ /*
+ * cc == 0 means the connection was broken at the other end.
+ */
+ else if (!cc)
+ return (STATUS_INVALID);
+
/*
fprintf(stderr,"expected packet of %d bytes, got %d bytes\n",
- packetLen, cc);
+ packetLen, cc);
*/
- tmp += cc;
- packetLen -= cc;
-
- /* if non-blocking, we're done. */
- if (nonBlocking && packetLen) {
- port->nBytes += cc;
- return(STATUS_NOT_DONE);
+ tmp += cc;
+ packetLen -= cc;
+
+ /* if non-blocking, we're done. */
+ if (nonBlocking && packetLen)
+ {
+ port->nBytes += cc;
+ return (STATUS_NOT_DONE);
+ }
}
- }
-
- port->nBytes = 0;
- return(STATUS_OK);
+
+ port->nBytes = 0;
+ return (STATUS_OK);
}
/*
@@ -192,46 +214,47 @@ PacketReceive(Port *port, /* receive port */
*
* RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
* SIDE_EFFECTS: may block.
- * NOTES: Non-blocking writes would significantly complicate
- * buffer management. For now, we're not going to do it.
+ * NOTES: Non-blocking writes would significantly complicate
+ * buffer management. For now, we're not going to do it.
*
*/
int
-PacketSend(Port *port,
- PacketBuf *buf,
- PacketLen len,
- bool nonBlocking)
+PacketSend(Port * port,
+ PacketBuf * buf,
+ PacketLen len,
+ bool nonBlocking)
{
- PacketLen totalLen;
- int addrLen = sizeof(struct sockaddr_in);
-
- Assert(!nonBlocking);
- Assert(buf);
-
- totalLen = len;
-
- len = sendto(port->sock, (Addr) buf, totalLen, /* flags */ 0,
- (struct sockaddr *)&(port->raddr), addrLen);
-
- if (len < totalLen) {
- sprintf(PQerrormsg,
- "FATAL: PacketSend: couldn't send complete packet: errno=%d\n",
- errno);
- fputs(PQerrormsg, stderr);
- return(STATUS_ERROR);
- }
-
- return(STATUS_OK);
+ PacketLen totalLen;
+ int addrLen = sizeof(struct sockaddr_in);
+
+ Assert(!nonBlocking);
+ Assert(buf);
+
+ totalLen = len;
+
+ len = sendto(port->sock, (Addr) buf, totalLen, /* flags */ 0,
+ (struct sockaddr *) & (port->raddr), addrLen);
+
+ if (len < totalLen)
+ {
+ sprintf(PQerrormsg,
+ "FATAL: PacketSend: couldn't send complete packet: errno=%d\n",
+ errno);
+ fputs(PQerrormsg, stderr);
+ return (STATUS_ERROR);
+ }
+
+ return (STATUS_OK);
}
/*
* StartupInfo2PacketBuf -
- * convert the fields of the StartupInfo to a PacketBuf
+ * convert the fields of the StartupInfo to a PacketBuf
*
*/
/* moved to src/libpq/fe-connect.c */
/*
-PacketBuf*
+PacketBuf*
StartupInfo2PacketBuf(StartupInfo* s)
{
PacketBuf* res;
@@ -259,10 +282,10 @@ StartupInfo2PacketBuf(StartupInfo* s)
/*
* PacketBuf2StartupInfo -
- * convert the fields of the StartupInfo to a PacketBuf
+ * convert the fields of the StartupInfo to a PacketBuf
*
*/
-/* moved to postmaster.c
+/* moved to postmaster.c
StartupInfo*
PacketBuf2StartupInfo(PacketBuf* p)
{