| 181 | } |
| 182 | |
| 183 | Status TlsSocket::Recv(uint8_t *buf, int32_t amt, int32_t *nread) { |
| 184 | SCOPED_OPENSSL_NO_PENDING_ERRORS; |
| 185 | |
| 186 | CHECK(ssl_); |
| 187 | errno = 0; |
| 188 | int32_t bytes_read = SSL_read(ssl_.get(), buf, amt); |
| 189 | int save_errno = errno; |
| 190 | if (bytes_read <= 0) { |
| 191 | Sockaddr remote; |
| 192 | Status s = GetPeerAddress(&remote); |
| 193 | const string remote_str = s.ok() ? remote.ToString() : "unknown"; |
| 194 | string kErrString = Substitute("failed to read from TLS socket (remote: $0)", |
| 195 | remote_str); |
| 196 | if (bytes_read == 0 && SSL_get_shutdown(ssl_.get()) == SSL_RECEIVED_SHUTDOWN) { |
| 197 | kErrString += GetOpenSSLErrors(); |
| 198 | return Status::NetworkError(kErrString, ErrnoToString(ESHUTDOWN), ESHUTDOWN); |
| 199 | } |
| 200 | auto error_code = SSL_get_error(ssl_.get(), bytes_read); |
| 201 | if (error_code == SSL_ERROR_WANT_READ) { |
| 202 | if (save_errno != 0) { |
| 203 | return Status::NetworkError("SSL_read error from " + remote_str, |
| 204 | ErrnoToString(save_errno), save_errno); |
| 205 | } |
| 206 | // Nothing available to read yet. |
| 207 | *nread = 0; |
| 208 | return Status::OK(); |
| 209 | } |
| 210 | if (error_code == SSL_ERROR_SYSCALL && ERR_peek_error() == 0) { |
| 211 | // From the OpenSSL docs: |
| 212 | // Some I/O error occurred. The OpenSSL error queue may contain more |
| 213 | // information on the error. If the error queue is empty (i.e. |
| 214 | // ERR_get_error() returns 0), ret can be used to find out more about |
| 215 | // the error: If ret == 0, an EOF was observed that violates the pro- |
| 216 | // tocol. If ret == -1, the underlying BIO reported an I/O error (for |
| 217 | // socket I/O on Unix systems, consult errno for details). |
| 218 | if (bytes_read == 0) { |
| 219 | // "EOF was observed that violates the protocol" (eg the other end disconnected) |
| 220 | return Status::NetworkError(kErrString, ErrnoToString(ECONNRESET), ECONNRESET); |
| 221 | } |
| 222 | if (bytes_read == -1 && save_errno != 0) { |
| 223 | return Status::NetworkError(kErrString, ErrnoToString(save_errno), save_errno); |
| 224 | } |
| 225 | return Status::NetworkError(kErrString, "unknown ERROR_SYSCALL"); |
| 226 | } |
| 227 | return Status::NetworkError(kErrString, GetSSLErrorDescription(error_code)); |
| 228 | } |
| 229 | *nread = bytes_read; |
| 230 | return Status::OK(); |
| 231 | } |
| 232 | |
| 233 | Status TlsSocket::Close() { |
| 234 | SCOPED_OPENSSL_NO_PENDING_ERRORS; |