/*-------------------------------------------------------------------- * Symbols referenced in this file: * - PqCommMethods *-------------------------------------------------------------------- */ /*------------------------------------------------------------------------- * * pqcomm.c * Communication functions between the Frontend and the Backend * * These routines handle the low-level details of communication between * frontend and backend. They just shove data across the communication * channel, and are ignorant of the semantics of the data --- or would be, * except for major brain damage in the design of the old COPY OUT protocol. * Unfortunately, COPY OUT was designed to commandeer the communication * channel (it just transfers data without wrapping it into messages). * No other messages can be sent while COPY OUT is in progress; and if the * copy is aborted by an ereport(ERROR), we need to close out the copy so that * the frontend gets back into sync. Therefore, these routines have to be * aware of COPY OUT state. (New COPY-OUT is message-based and does *not* * set the DoingCopyOut flag.) * * NOTE: generally, it's a bad idea to emit outgoing messages directly with * pq_putbytes(), especially if the message would require multiple calls * to send. Instead, use the routines in pqformat.c to construct the message * in a buffer and then emit it in one call to pq_putmessage. This ensures * that the channel will not be clogged by an incomplete message if execution * is aborted by ereport(ERROR) partway through the message. The only * non-libpq code that should call pq_putbytes directly is old-style COPY OUT. * * At one time, libpq was shared between frontend and backend, but now * the backend's "backend/libpq" is quite separate from "interfaces/libpq". * All that remains is similarities of names to trap the unwary... * * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/libpq/pqcomm.c * *------------------------------------------------------------------------- */ /*------------------------ * INTERFACE ROUTINES * * setup/teardown: * StreamServerPort - Open postmaster's server port * StreamConnection - Create new connection with client * StreamClose - Close a client/backend connection * TouchSocketFiles - Protect socket files against /tmp cleaners * pq_init - initialize libpq at backend startup * pq_comm_reset - reset libpq during error recovery * pq_close - shutdown libpq at backend exit * * low-level I/O: * pq_getbytes - get a known number of bytes from connection * pq_getstring - get a null terminated string from connection * pq_getmessage - get a message with length word from connection * pq_getbyte - get next byte from connection * pq_peekbyte - peek at next byte from connection * pq_putbytes - send bytes to connection (not flushed until pq_flush) * pq_flush - flush pending output * pq_flush_if_writable - flush pending output if writable without blocking * pq_getbyte_if_available - get a byte if available without blocking * * message-level I/O (and old-style-COPY-OUT cruft): * pq_putmessage - send a normal message (suppressed in COPY OUT mode) * pq_putmessage_noblock - buffer a normal message (suppressed in COPY OUT) * pq_startcopyout - inform libpq that a COPY OUT transfer is beginning * pq_endcopyout - end a COPY OUT transfer * *------------------------ */ #include "postgres.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_NETINET_TCP_H #include #endif #include #ifdef HAVE_UTIME_H #include #endif #ifdef WIN32_ONLY_COMPILER /* mstcpip.h is missing on mingw */ #include #endif #include "libpq/ip.h" #include "libpq/libpq.h" #include "miscadmin.h" #include "storage/ipc.h" #include "utils/guc.h" #include "utils/memutils.h" /* * Configuration options */ /* Where the Unix socket files are (list of palloc'd strings) */ /* * Buffers for low-level I/O. * * The receive buffer is fixed size. Send buffer is usually 8k, but can be * enlarged by pq_putmessage_noblock() if the message doesn't fit otherwise. */ #define PQ_SEND_BUFFER_SIZE 8192 #define PQ_RECV_BUFFER_SIZE 8192 /* Size send buffer */ /* Next index to store a byte in PqSendBuffer */ /* Next index to send a byte in PqSendBuffer */ /* Next index to read a byte from PqRecvBuffer */ /* End of data available in PqRecvBuffer */ /* * Message status */ /* busy sending data to the client */ /* in the middle of reading a message */ /* in old-protocol COPY OUT processing */ /* Internal functions */ static void socket_comm_reset(void); static void socket_close(int code, Datum arg); static void socket_set_nonblocking(bool nonblocking); static int socket_flush(void); static int socket_flush_if_writable(void); static bool socket_is_send_pending(void); static int socket_putmessage(char msgtype, const char *s, size_t len); static void socket_putmessage_noblock(char msgtype, const char *s, size_t len); static void socket_startcopyout(void); static void socket_endcopyout(bool errorAbort); static int internal_putbytes(const char *s, size_t len); static int internal_flush(void); static void socket_set_nonblocking(bool nonblocking); #ifdef HAVE_UNIX_SOCKETS static int Lock_AF_UNIX(char *unixSocketDir, char *unixSocketPath); static int Setup_AF_UNIX(char *sock_path); #endif /* HAVE_UNIX_SOCKETS */ PQcommMethods *PqCommMethods = NULL; /* -------------------------------- * pq_init - initialize libpq at backend startup * -------------------------------- */ #ifndef WIN32 #endif /* -------------------------------- * socket_comm_reset - reset libpq during error recovery * * This is called from error recovery at the outer idle loop. It's * just to get us out of trouble if we somehow manage to elog() from * inside a pqcomm.c routine (which ideally will never happen, but...) * -------------------------------- */ /* -------------------------------- * socket_close - shutdown libpq at backend exit * * This is the one pg_on_exit_callback in place during BackendInitialize(). * That function's unusual signal handling constrains that this callback be * safe to run at any instant. * -------------------------------- */ #if defined(ENABLE_GSS) || defined(ENABLE_SSPI) #ifdef ENABLE_GSS #endif /* ENABLE_GSS */ #endif /* ENABLE_GSS || ENABLE_SSPI */ /* * Streams -- wrapper around Unix socket system calls * * * Stream functions are used for vanilla TCP connection protocol. */ /* * StreamServerPort -- open a "listening" port to accept connections. * * family should be AF_UNIX or AF_UNSPEC; portNumber is the port number. * For AF_UNIX ports, hostName should be NULL and unixSocketDir must be * specified. For TCP ports, hostName is either NULL for all interfaces or * the interface to listen on, and unixSocketDir is ignored (can be NULL). * * Successfully opened sockets are added to the ListenSocket[] array (of * length MaxListen), at the first position that isn't PGINVALID_SOCKET. * * RETURNS: STATUS_OK or STATUS_ERROR */ #ifdef HAVE_UNIX_SOCKETS #endif #if !defined(WIN32) || defined(IPV6_V6ONLY) #endif #ifdef HAVE_UNIX_SOCKETS #endif /* HAVE_UNIX_SOCKETS */ #ifdef HAVE_IPV6 #endif #ifdef HAVE_UNIX_SOCKETS #endif #ifndef WIN32 #endif #ifdef IPV6_V6ONLY #endif #ifdef HAVE_UNIX_SOCKETS #endif #ifdef HAVE_UNIX_SOCKETS /* * Lock_AF_UNIX -- configure unix socket file path */ /* * Setup_AF_UNIX -- configure unix socket permissions */ #ifdef WIN32 #else #endif #endif /* HAVE_UNIX_SOCKETS */ /* * StreamConnection -- create a new connection with client using * server port. Set port->sock to the FD of the new connection. * * ASSUME: that this doesn't need to be non-blocking because * the Postmaster uses select() to tell when the server master * socket is ready for accept(). * * RETURNS: STATUS_OK or STATUS_ERROR */ #ifdef SCO_ACCEPT_BUG #endif #ifdef TCP_NODELAY #endif #ifdef WIN32 #endif /* * StreamClose -- close a client/backend connection * * NOTE: this is NOT used to terminate a session; it is just used to release * the file descriptor in a process that should no longer have the socket * open. (For example, the postmaster calls this after passing ownership * of the connection to a child process.) It is expected that someone else * still has the socket open. So, we only want to close the descriptor, * we do NOT want to send anything to the far end. */ /* * TouchSocketFiles -- mark socket files as recently accessed * * This routine should be called every so often to ensure that the socket * files have a recent mod date (ordinary operations on sockets usually won't * change the mod date). That saves them from being removed by * overenthusiastic /tmp-directory-cleaner daemons. (Another reason we should * never have put the socket file in /tmp...) */ #ifdef HAVE_UTIME #else /* !HAVE_UTIME */ #ifdef HAVE_UTIMES #endif /* HAVE_UTIMES */ #endif /* HAVE_UTIME */ /* * RemoveSocketFiles -- unlink socket files at postmaster shutdown */ /* -------------------------------- * Low-level I/O routines begin here. * * These routines communicate with a frontend client across a connection * already established by the preceding routines. * -------------------------------- */ /* -------------------------------- * socket_set_nonblocking - set socket blocking/non-blocking * * Sets the socket non-blocking if nonblocking is TRUE, or sets it * blocking otherwise. * -------------------------------- */ /* -------------------------------- * pq_recvbuf - load some bytes into the input buffer * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * pq_getbyte - get a single byte from connection, or return EOF * -------------------------------- */ /* -------------------------------- * pq_peekbyte - peek at next byte from connection * * Same as pq_getbyte() except we don't advance the pointer. * -------------------------------- */ /* -------------------------------- * pq_getbyte_if_available - get a single byte from connection, * if available * * The received byte is stored in *c. Returns 1 if a byte was read, * 0 if no data was available, or EOF if trouble. * -------------------------------- */ /* -------------------------------- * pq_getbytes - get a known number of bytes from connection * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * pq_discardbytes - throw away a known number of bytes * * same as pq_getbytes except we do not copy the data to anyplace. * this is used for resynchronizing after read errors. * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * pq_getstring - get a null terminated string from connection * * The return value is placed in an expansible StringInfo, which has * already been initialized by the caller. * * This is used only for dealing with old-protocol clients. The idea * is to produce a StringInfo that looks the same as we would get from * pq_getmessage() with a newer client; we will then process it with * pq_getmsgstring. Therefore, no character set conversion is done here, * even though this is presumably useful only for text. * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * pq_startmsgread - begin reading a message from the client. * * This must be called before any of the pq_get* functions. * -------------------------------- */ /* -------------------------------- * pq_endmsgread - finish reading message. * * This must be called after reading a V2 protocol message with * pq_getstring() and friends, to indicate that we have read the whole * message. In V3 protocol, pq_getmessage() does this implicitly. * -------------------------------- */ /* -------------------------------- * pq_is_reading_msg - are we currently reading a message? * * This is used in error recovery at the outer idle loop to detect if we have * lost protocol sync, and need to terminate the connection. pq_startmsgread() * will check for that too, but it's nicer to detect it earlier. * -------------------------------- */ /* -------------------------------- * pq_getmessage - get a message with length word from connection * * The return value is placed in an expansible StringInfo, which has * already been initialized by the caller. * Only the message body is placed in the StringInfo; the length word * is removed. Also, s->cursor is initialized to zero for convenience * in scanning the message contents. * * If maxlen is not zero, it is an upper limit on the length of the * message we are willing to accept. We abort the connection (by * returning EOF) if client tries to send more than that. * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * pq_putbytes - send bytes to connection (not flushed until pq_flush) * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * socket_flush - flush pending output * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * internal_flush - flush pending output * * Returns 0 if OK (meaning everything was sent, or operation would block * and the socket is in non-blocking mode), or EOF if trouble. * -------------------------------- */ /* -------------------------------- * pq_flush_if_writable - flush pending output if writable without blocking * * Returns 0 if OK, or EOF if trouble. * -------------------------------- */ /* -------------------------------- * socket_is_send_pending - is there any pending data in the output buffer? * -------------------------------- */ /* -------------------------------- * Message-level I/O routines begin here. * * These routines understand about the old-style COPY OUT protocol. * -------------------------------- */ /* -------------------------------- * socket_putmessage - send a normal message (suppressed in COPY OUT mode) * * If msgtype is not '\0', it is a message type code to place before * the message body. If msgtype is '\0', then the message has no type * code (this is only valid in pre-3.0 protocols). * * len is the length of the message body data at *s. In protocol 3.0 * and later, a message length word (equal to len+4 because it counts * itself too) is inserted by this routine. * * All normal messages are suppressed while old-style COPY OUT is in * progress. (In practice only a few notice messages might get emitted * then; dropping them is annoying, but at least they will still appear * in the postmaster log.) * * We also suppress messages generated while pqcomm.c is busy. This * avoids any possibility of messages being inserted within other * messages. The only known trouble case arises if SIGQUIT occurs * during a pqcomm.c routine --- quickdie() will try to send a warning * message, and the most reasonable approach seems to be to drop it. * * returns 0 if OK, EOF if trouble * -------------------------------- */ /* -------------------------------- * pq_putmessage_noblock - like pq_putmessage, but never blocks * * If the output buffer is too small to hold the message, the buffer * is enlarged. */ /* -------------------------------- * socket_startcopyout - inform libpq that an old-style COPY OUT transfer * is beginning * -------------------------------- */ /* -------------------------------- * socket_endcopyout - end an old-style COPY OUT transfer * * If errorAbort is indicated, we are aborting a COPY OUT due to an error, * and must send a terminator line. Since a partial data line might have * been emitted, send a couple of newlines first (the first one could * get absorbed by a backslash...) Note that old-style COPY OUT does * not allow binary transfers, so a textual terminator is always correct. * -------------------------------- */ /* * Support for TCP Keepalive parameters */ /* * On Windows, we need to set both idle and interval at the same time. * We also cannot reset them to the default (setting to zero will * actually set them to zero, not default), therefore we fallback to * the out-of-the-box default instead. */ #if defined(WIN32) && defined(SIO_KEEPALIVE_VALS) static int pq_setkeepaliveswin32(Port *port, int idle, int interval) { struct tcp_keepalive ka; DWORD retsize; if (idle <= 0) idle = 2 * 60 * 60; /* default = 2 hours */ if (interval <= 0) interval = 1; /* default = 1 second */ ka.onoff = 1; ka.keepalivetime = idle * 1000; ka.keepaliveinterval = interval * 1000; if (WSAIoctl(port->sock, SIO_KEEPALIVE_VALS, (LPVOID) &ka, sizeof(ka), NULL, 0, &retsize, NULL, NULL) != 0) { elog(LOG, "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui", WSAGetLastError()); return STATUS_ERROR; } if (port->keepalives_idle != idle) port->keepalives_idle = idle; if (port->keepalives_interval != interval) port->keepalives_interval = interval; return STATUS_OK; } #endif #if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(WIN32) #ifndef WIN32 #ifdef TCP_KEEPIDLE #else #endif /* TCP_KEEPIDLE */ #else /* WIN32 */ #endif /* WIN32 */ #else #endif #if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS) #ifndef WIN32 #ifdef TCP_KEEPIDLE #else #endif #else /* WIN32 */ #endif #else /* TCP_KEEPIDLE || SIO_KEEPALIVE_VALS */ #endif #if defined(TCP_KEEPINTVL) || defined(SIO_KEEPALIVE_VALS) #ifndef WIN32 #else #endif /* WIN32 */ #else #endif #if defined(TCP_KEEPINTVL) || defined (SIO_KEEPALIVE_VALS) #ifndef WIN32 #else /* WIN32 */ #endif #else #endif #ifdef TCP_KEEPCNT #else #endif #ifdef TCP_KEEPCNT #else #endif