diff options
Diffstat (limited to 'src/backend/libpq/pqpacket.c')
-rw-r--r-- | src/backend/libpq/pqpacket.c | 361 |
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) { |