/* are we in the middle of a renegotiation? */
static bool in_ssl_renegotiation = false;
+/* kill-switch to have my_sock_read pretend there's no data */
+static bool my_block_raw_read = false;
+
static SSL_CTX *SSL_context = NULL;
static bool ssl_loaded_verify_locations = false;
#endif
wloop:
errno = 0;
+ my_block_raw_read = true;
n = SSL_write(port->ssl, ptr, len);
+ my_block_raw_read = false;
err = SSL_get_error(port->ssl, n);
switch (err)
{
FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
INFINITE);
#endif
+ if (err == SSL_ERROR_WANT_READ)
+ {
+ if (pq_recvbuf(false) != 0)
+ {
+ errno = ECONNRESET;
+ n = -1;
+ break;
+ }
+ }
goto wloop;
case SSL_ERROR_SYSCALL:
/* leave it to caller to ereport the value of errno */
{
int res = 0;
- prepare_for_client_read();
+ if (buf == NULL)
+ return 0; /* XXX: can this happen? */
- if (buf != NULL)
+ /* If the kill-switch is set, pretend that there is no data. */
+ if (my_block_raw_read)
{
- res = recv(h->num, buf, size, 0);
BIO_clear_retry_flags(h);
- if (res <= 0)
+ BIO_set_retry_read(h);
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ prepare_for_client_read();
+
+ res = recv(h->num, buf, size, 0);
+ BIO_clear_retry_flags(h);
+ if (res <= 0)
+ {
+ /* If we were interrupted, tell caller to retry */
+ if (errno == EINTR)
{
- /* If we were interrupted, tell caller to retry */
- if (errno == EINTR)
- {
- BIO_set_retry_read(h);
- }
+ BIO_set_retry_read(h);
}
}
/* --------------------------------
* pq_recvbuf - load some bytes into the input buffer
*
- * returns 0 if OK, EOF if trouble
+ * returns 0 if OK, EOF if trouble
* --------------------------------
*/
-static int
-pq_recvbuf(void)
+int
+pq_recvbuf(bool block)
{
if (PqRecvPointer > 0)
{
PqRecvLength = PqRecvPointer = 0;
}
- /* Ensure that we're in blocking mode */
- pq_set_nonblocking(false);
+ /* Ensure that we're in blocking mode (or not) */
+ pq_set_nonblocking(!block);
/* Can fill buffer from PqRecvLength and upwards */
for (;;)
if (errno == EINTR)
continue; /* Ok if interrupted */
+ if (!block)
+ {
+ if (errno == EWOULDBLOCK || errno == EAGAIN)
+ return 0;
+ }
+
/*
* Careful: an ereport() that tries to write to the client would
* cause recursion to here, leading to stack overflow and core
while (PqRecvPointer >= PqRecvLength)
{
- if (pq_recvbuf()) /* If nothing in buffer, then recv some */
+ if (pq_recvbuf(true)) /* If nothing in buffer, then recv some */
return EOF; /* Failed to recv data */
}
return (unsigned char) PqRecvBuffer[PqRecvPointer++];
{
while (PqRecvPointer >= PqRecvLength)
{
- if (pq_recvbuf()) /* If nothing in buffer, then recv some */
+ if (pq_recvbuf(true)) /* If nothing in buffer, then recv some */
return EOF; /* Failed to recv data */
}
return (unsigned char) PqRecvBuffer[PqRecvPointer];
{
while (PqRecvPointer >= PqRecvLength)
{
- if (pq_recvbuf()) /* If nothing in buffer, then recv some */
+ if (pq_recvbuf(true)) /* If nothing in buffer, then recv some */
return EOF; /* Failed to recv data */
}
amount = PqRecvLength - PqRecvPointer;
{
while (PqRecvPointer >= PqRecvLength)
{
- if (pq_recvbuf()) /* If nothing in buffer, then recv some */
+ if (pq_recvbuf(true)) /* If nothing in buffer, then recv some */
return EOF; /* Failed to recv data */
}
amount = PqRecvLength - PqRecvPointer;
{
while (PqRecvPointer >= PqRecvLength)
{
- if (pq_recvbuf()) /* If nothing in buffer, then recv some */
+ if (pq_recvbuf(true)) /* If nothing in buffer, then recv some */
return EOF; /* Failed to recv data */
}