Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
crypto/tls: make Conn.Read return (n, io.EOF) when EOF is next in buffer Update #3514 An io.Reader is permitted to return either (n, nil) or (n, io.EOF) on EOF or other error. The tls package previously always returned (n, nil) for a read of size n if n bytes were available, not surfacing errors at the same time. Amazon's HTTPS frontends like to hang up on clients without sending the appropriate HTTP headers. (In their defense, they're allowed to hang up any time, but generally a server hangs up after a bit of inactivity, not immediately.) In any case, the Go HTTP client tries to re-use connections by looking at whether the response headers say to keep the connection open, and because the connection looks okay, under heavy load it's possible we'll reuse it immediately, writing the next request, just as the Transport's always-reading goroutine returns from tls.Conn.Read and sees (0, io.EOF). But because Amazon does send an AlertCloseNotify record before it hangs up on us, and the tls package does its own internal buffering (up to 1024 bytes) of pending data, we have the AlertCloseNotify in an unread buffer when our Conn.Read (to the HTTP Transport code) reads its final bit of data in the HTTP response body. This change makes that final Read return (n, io.EOF) when an AlertCloseNotify record is buffered right after, if we'd otherwise return (n, nil). A dependent change in the HTTP code then notes whether a client connection has seen an io.EOF and uses that as an additional signal to not reuse a HTTPS connection. With both changes, the majority of Amazon request failures go away. Without either one, 10-20 goroutines hitting the S3 API leads to such an error rate that empirically up to 5 retries are needed to complete an API call. LGTM=agl, rsc R=agl, rsc CC=golang-codereviews https://golang.org/cl/76400046
vor 10 Jahren
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. // Copyright 2012 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package tls
  5. import (
  6. "bytes"
  7. "errors"
  8. "fmt"
  9. "internal/testenv"
  10. "io"
  11. "net"
  12. "strings"
  13. "testing"
  14. "time"
  15. )
  16. var rsaCertPEM = `-----BEGIN CERTIFICATE-----
  17. MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
  18. BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
  19. aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
  20. MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
  21. ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
  22. hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
  23. rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
  24. zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
  25. MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
  26. r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
  27. -----END CERTIFICATE-----
  28. `
  29. var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
  30. MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
  31. k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
  32. 6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
  33. MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
  34. SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
  35. xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
  36. D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
  37. -----END RSA PRIVATE KEY-----
  38. `
  39. // keyPEM is the same as rsaKeyPEM, but declares itself as just
  40. // "PRIVATE KEY", not "RSA PRIVATE KEY". https://golang.org/issue/4477
  41. var keyPEM = `-----BEGIN PRIVATE KEY-----
  42. MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
  43. k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
  44. 6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
  45. MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
  46. SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
  47. xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
  48. D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
  49. -----END PRIVATE KEY-----
  50. `
  51. var ecdsaCertPEM = `-----BEGIN CERTIFICATE-----
  52. MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
  53. EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
  54. eSBMdGQwHhcNMTIxMTE0MTI0MDQ4WhcNMTUxMTE0MTI0MDQ4WjBFMQswCQYDVQQG
  55. EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk
  56. Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBY9+my9OoeSUR
  57. lDQdV/x8LsOuLilthhiS1Tz4aGDHIPwC1mlvnf7fg5lecYpMCrLLhauAc1UJXcgl
  58. 01xoLuzgtAEAgv2P/jgytzRSpUYvgLBt1UA0leLYBy6mQQbrNEuqT3INapKIcUv8
  59. XxYP0xMEUksLPq6Ca+CRSqTtrd/23uTnapkwCQYHKoZIzj0EAQOBigAwgYYCQXJo
  60. A7Sl2nLVf+4Iu/tAX/IF4MavARKC4PPHK3zfuGfPR3oCCcsAoz3kAzOeijvd0iXb
  61. H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1
  62. +jwM1FGS4fREIOvlBYr/SzzQRtwrvrzGYxDEDbsC0ZGRnA==
  63. -----END CERTIFICATE-----
  64. `
  65. var ecdsaKeyPEM = `-----BEGIN EC PARAMETERS-----
  66. BgUrgQQAIw==
  67. -----END EC PARAMETERS-----
  68. -----BEGIN EC PRIVATE KEY-----
  69. MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0
  70. NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL
  71. 06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz
  72. VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q
  73. kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ==
  74. -----END EC PRIVATE KEY-----
  75. `
  76. var keyPairTests = []struct {
  77. algo string
  78. cert string
  79. key string
  80. }{
  81. {"ECDSA", ecdsaCertPEM, ecdsaKeyPEM},
  82. {"RSA", rsaCertPEM, rsaKeyPEM},
  83. {"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477
  84. }
  85. func TestX509KeyPair(t *testing.T) {
  86. var pem []byte
  87. for _, test := range keyPairTests {
  88. pem = []byte(test.cert + test.key)
  89. if _, err := X509KeyPair(pem, pem); err != nil {
  90. t.Errorf("Failed to load %s cert followed by %s key: %s", test.algo, test.algo, err)
  91. }
  92. pem = []byte(test.key + test.cert)
  93. if _, err := X509KeyPair(pem, pem); err != nil {
  94. t.Errorf("Failed to load %s key followed by %s cert: %s", test.algo, test.algo, err)
  95. }
  96. }
  97. }
  98. func TestX509KeyPairErrors(t *testing.T) {
  99. _, err := X509KeyPair([]byte(rsaKeyPEM), []byte(rsaCertPEM))
  100. if err == nil {
  101. t.Fatalf("X509KeyPair didn't return an error when arguments were switched")
  102. }
  103. if subStr := "been switched"; !strings.Contains(err.Error(), subStr) {
  104. t.Fatalf("Expected %q in the error when switching arguments to X509KeyPair, but the error was %q", subStr, err)
  105. }
  106. _, err = X509KeyPair([]byte(rsaCertPEM), []byte(rsaCertPEM))
  107. if err == nil {
  108. t.Fatalf("X509KeyPair didn't return an error when both arguments were certificates")
  109. }
  110. if subStr := "certificate"; !strings.Contains(err.Error(), subStr) {
  111. t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were certificates, but the error was %q", subStr, err)
  112. }
  113. const nonsensePEM = `
  114. -----BEGIN NONSENSE-----
  115. Zm9vZm9vZm9v
  116. -----END NONSENSE-----
  117. `
  118. _, err = X509KeyPair([]byte(nonsensePEM), []byte(nonsensePEM))
  119. if err == nil {
  120. t.Fatalf("X509KeyPair didn't return an error when both arguments were nonsense")
  121. }
  122. if subStr := "NONSENSE"; !strings.Contains(err.Error(), subStr) {
  123. t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were nonsense, but the error was %q", subStr, err)
  124. }
  125. }
  126. func TestX509MixedKeyPair(t *testing.T) {
  127. if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil {
  128. t.Error("Load of RSA certificate succeeded with ECDSA private key")
  129. }
  130. if _, err := X509KeyPair([]byte(ecdsaCertPEM), []byte(rsaKeyPEM)); err == nil {
  131. t.Error("Load of ECDSA certificate succeeded with RSA private key")
  132. }
  133. }
  134. func newLocalListener(t *testing.T) net.Listener {
  135. ln, err := net.Listen("tcp", "127.0.0.1:0")
  136. if err != nil {
  137. ln, err = net.Listen("tcp6", "[::1]:0")
  138. }
  139. if err != nil {
  140. t.Fatal(err)
  141. }
  142. return ln
  143. }
  144. func TestDialTimeout(t *testing.T) {
  145. if testing.Short() {
  146. t.Skip("skipping in short mode")
  147. }
  148. listener := newLocalListener(t)
  149. addr := listener.Addr().String()
  150. defer listener.Close()
  151. complete := make(chan bool)
  152. defer close(complete)
  153. go func() {
  154. conn, err := listener.Accept()
  155. if err != nil {
  156. t.Error(err)
  157. return
  158. }
  159. <-complete
  160. conn.Close()
  161. }()
  162. dialer := &net.Dialer{
  163. Timeout: 10 * time.Millisecond,
  164. }
  165. var err error
  166. if _, err = DialWithDialer(dialer, "tcp", addr, nil); err == nil {
  167. t.Fatal("DialWithTimeout completed successfully")
  168. }
  169. if !strings.Contains(err.Error(), "timed out") {
  170. t.Errorf("resulting error not a timeout: %s", err)
  171. }
  172. }
  173. // tests that Conn.Read returns (non-zero, io.EOF) instead of
  174. // (non-zero, nil) when a Close (alertCloseNotify) is sitting right
  175. // behind the application data in the buffer.
  176. func TestConnReadNonzeroAndEOF(t *testing.T) {
  177. // This test is racy: it assumes that after a write to a
  178. // localhost TCP connection, the peer TCP connection can
  179. // immediately read it. Because it's racy, we skip this test
  180. // in short mode, and then retry it several times with an
  181. // increasing sleep in between our final write (via srv.Close
  182. // below) and the following read.
  183. if testing.Short() {
  184. t.Skip("skipping in short mode")
  185. }
  186. var err error
  187. for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 {
  188. if err = testConnReadNonzeroAndEOF(t, delay); err == nil {
  189. return
  190. }
  191. }
  192. t.Error(err)
  193. }
  194. func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
  195. ln := newLocalListener(t)
  196. defer ln.Close()
  197. srvCh := make(chan *Conn, 1)
  198. var serr error
  199. go func() {
  200. sconn, err := ln.Accept()
  201. if err != nil {
  202. serr = err
  203. srvCh <- nil
  204. return
  205. }
  206. serverConfig := *testConfig
  207. srv := Server(sconn, &serverConfig)
  208. if err := srv.Handshake(); err != nil {
  209. serr = fmt.Errorf("handshake: %v", err)
  210. srvCh <- nil
  211. return
  212. }
  213. srvCh <- srv
  214. }()
  215. clientConfig := *testConfig
  216. conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
  217. if err != nil {
  218. t.Fatal(err)
  219. }
  220. defer conn.Close()
  221. srv := <-srvCh
  222. if srv == nil {
  223. return serr
  224. }
  225. buf := make([]byte, 6)
  226. srv.Write([]byte("foobar"))
  227. n, err := conn.Read(buf)
  228. if n != 6 || err != nil || string(buf) != "foobar" {
  229. return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
  230. }
  231. srv.Write([]byte("abcdef"))
  232. srv.Close()
  233. time.Sleep(delay)
  234. n, err = conn.Read(buf)
  235. if n != 6 || string(buf) != "abcdef" {
  236. return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf)
  237. }
  238. if err != io.EOF {
  239. return fmt.Errorf("Second Read error = %v; want io.EOF", err)
  240. }
  241. return nil
  242. }
  243. func TestTLSUniqueMatches(t *testing.T) {
  244. ln := newLocalListener(t)
  245. defer ln.Close()
  246. serverTLSUniques := make(chan []byte)
  247. go func() {
  248. for i := 0; i < 2; i++ {
  249. sconn, err := ln.Accept()
  250. if err != nil {
  251. t.Fatal(err)
  252. }
  253. serverConfig := *testConfig
  254. srv := Server(sconn, &serverConfig)
  255. if err := srv.Handshake(); err != nil {
  256. t.Fatal(err)
  257. }
  258. serverTLSUniques <- srv.ConnectionState().TLSUnique
  259. }
  260. }()
  261. clientConfig := *testConfig
  262. clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
  263. conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
  264. if err != nil {
  265. t.Fatal(err)
  266. }
  267. if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
  268. t.Error("client and server channel bindings differ")
  269. }
  270. conn.Close()
  271. conn, err = Dial("tcp", ln.Addr().String(), &clientConfig)
  272. if err != nil {
  273. t.Fatal(err)
  274. }
  275. defer conn.Close()
  276. if !conn.ConnectionState().DidResume {
  277. t.Error("second session did not use resumption")
  278. }
  279. if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
  280. t.Error("client and server channel bindings differ when session resumption is used")
  281. }
  282. }
  283. func TestVerifyHostname(t *testing.T) {
  284. testenv.MustHaveExternalNetwork(t)
  285. c, err := Dial("tcp", "www.google.com:https", nil)
  286. if err != nil {
  287. t.Fatal(err)
  288. }
  289. if err := c.VerifyHostname("www.google.com"); err != nil {
  290. t.Fatalf("verify www.google.com: %v", err)
  291. }
  292. if err := c.VerifyHostname("www.yahoo.com"); err == nil {
  293. t.Fatalf("verify www.yahoo.com succeeded")
  294. }
  295. c, err = Dial("tcp", "www.google.com:https", &Config{InsecureSkipVerify: true})
  296. if err != nil {
  297. t.Fatal(err)
  298. }
  299. if err := c.VerifyHostname("www.google.com"); err == nil {
  300. t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
  301. }
  302. if err := c.VerifyHostname("www.yahoo.com"); err == nil {
  303. t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
  304. }
  305. }
  306. func TestVerifyHostnameResumed(t *testing.T) {
  307. testenv.MustHaveExternalNetwork(t)
  308. config := &Config{
  309. ClientSessionCache: NewLRUClientSessionCache(32),
  310. }
  311. for i := 0; i < 2; i++ {
  312. c, err := Dial("tcp", "www.google.com:https", config)
  313. if err != nil {
  314. t.Fatalf("Dial #%d: %v", i, err)
  315. }
  316. cs := c.ConnectionState()
  317. if i > 0 && !cs.DidResume {
  318. t.Fatalf("Subsequent connection unexpectedly didn't resume")
  319. }
  320. if cs.VerifiedChains == nil {
  321. t.Fatalf("Dial #%d: cs.VerifiedChains == nil", i)
  322. }
  323. if err := c.VerifyHostname("www.google.com"); err != nil {
  324. t.Fatalf("verify www.google.com #%d: %v", i, err)
  325. }
  326. c.Close()
  327. }
  328. }
  329. func TestConnCloseBreakingWrite(t *testing.T) {
  330. ln := newLocalListener(t)
  331. defer ln.Close()
  332. srvCh := make(chan *Conn, 1)
  333. var serr error
  334. var sconn net.Conn
  335. go func() {
  336. var err error
  337. sconn, err = ln.Accept()
  338. if err != nil {
  339. serr = err
  340. srvCh <- nil
  341. return
  342. }
  343. serverConfig := *testConfig
  344. srv := Server(sconn, &serverConfig)
  345. if err := srv.Handshake(); err != nil {
  346. serr = fmt.Errorf("handshake: %v", err)
  347. srvCh <- nil
  348. return
  349. }
  350. srvCh <- srv
  351. }()
  352. cconn, err := net.Dial("tcp", ln.Addr().String())
  353. if err != nil {
  354. t.Fatal(err)
  355. }
  356. defer cconn.Close()
  357. conn := &changeImplConn{
  358. Conn: cconn,
  359. }
  360. clientConfig := *testConfig
  361. tconn := Client(conn, &clientConfig)
  362. if err := tconn.Handshake(); err != nil {
  363. t.Fatal(err)
  364. }
  365. srv := <-srvCh
  366. if srv == nil {
  367. t.Fatal(serr)
  368. }
  369. defer sconn.Close()
  370. connClosed := make(chan struct{})
  371. conn.closeFunc = func() error {
  372. close(connClosed)
  373. return nil
  374. }
  375. inWrite := make(chan bool, 1)
  376. var errConnClosed = errors.New("conn closed for test")
  377. conn.writeFunc = func(p []byte) (n int, err error) {
  378. inWrite <- true
  379. <-connClosed
  380. return 0, errConnClosed
  381. }
  382. closeReturned := make(chan bool, 1)
  383. go func() {
  384. <-inWrite
  385. tconn.Close() // test that this doesn't block forever.
  386. closeReturned <- true
  387. }()
  388. _, err = tconn.Write([]byte("foo"))
  389. if err != errConnClosed {
  390. t.Errorf("Write error = %v; want errConnClosed", err)
  391. }
  392. <-closeReturned
  393. if err := tconn.Close(); err != errClosed {
  394. t.Errorf("Close error = %v; want errClosed", err)
  395. }
  396. }
  397. // changeImplConn is a net.Conn which can change its Write and Close
  398. // methods.
  399. type changeImplConn struct {
  400. net.Conn
  401. writeFunc func([]byte) (int, error)
  402. closeFunc func() error
  403. }
  404. func (w *changeImplConn) Write(p []byte) (n int, err error) {
  405. if w.writeFunc != nil {
  406. return w.writeFunc(p)
  407. }
  408. return w.Conn.Write(p)
  409. }
  410. func (w *changeImplConn) Close() error {
  411. if w.closeFunc != nil {
  412. return w.closeFunc()
  413. }
  414. return w.Conn.Close()
  415. }