Browse Source

Reorganize code in package graceful

Exactly the same code, just (hopefully) organized a little more
sensibly.
Carl Jackson 11 years ago
parent
commit
1230cef060
3 changed files with 109 additions and 104 deletions
  1. +27
    -77
      graceful/graceful.go
  2. +82
    -0
      graceful/server.go
  3. +0
    -27
      graceful/signal.go

+ 27
- 77
graceful/graceful.go View File

@ -8,88 +8,12 @@ automatic support for graceful restarts/code upgrades.
package graceful
import (
"crypto/tls"
"net"
"net/http"
"sync/atomic"
"github.com/zenazn/goji/graceful/listener"
)
// Most of the code here is lifted straight from net/http
// Type Server is exactly the same as an http.Server, but provides more graceful
// implementations of its methods.
type Server http.Server
func (srv *Server) ListenAndServe() error {
addr := srv.Addr
if addr == "" {
addr = ":http"
}
l, e := net.Listen("tcp", addr)
if e != nil {
return e
}
return srv.Serve(l)
}
// Unlike the method of the same name on http.Server, this function defaults to
// enforcing TLS 1.0 or higher in order to address the POODLE vulnerability.
// Users who wish to enable SSLv3 must do so by supplying a TLSConfig
// explicitly.
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
addr := srv.Addr
if addr == "" {
addr = ":https"
}
config := &tls.Config{
MinVersion: tls.VersionTLS10,
}
if srv.TLSConfig != nil {
*config = *srv.TLSConfig
}
if config.NextProtos == nil {
config.NextProtos = []string{"http/1.1"}
}
var err error
config.Certificates = make([]tls.Certificate, 1)
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return err
}
conn, err := net.Listen("tcp", addr)
if err != nil {
return err
}
tlsListener := tls.NewListener(conn, config)
return srv.Serve(tlsListener)
}
// ListenAndServe behaves exactly like the net/http function of the same name.
func ListenAndServe(addr string, handler http.Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
// ListenAndServeTLS behaves almost exactly like the net/http function of the
// same name. Unlike net/http, however, this function defaults to enforcing TLS
// 1.0 or higher in order to address the POODLE vulnerability. Users who wish to
// enable SSLv3 must do so by explicitly instantiating a server with an
// appropriately configured TLSConfig property.
func ListenAndServeTLS(addr, certfile, keyfile string, handler http.Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServeTLS(certfile, keyfile)
}
// Serve behaves exactly like the net/http function of the same name.
func Serve(l net.Listener, handler http.Handler) error {
server := &Server{Handler: handler}
return server.Serve(l)
}
// WrapListener wraps an arbitrary net.Listener for use with graceful shutdowns.
// In the background, it uses the listener sub-package to Wrap the listener in
// Deadline mode. If another mode of operation is desired, you should call
@ -105,3 +29,29 @@ func WrapListener(l net.Listener) net.Listener {
appendListener(lt)
return lt
}
func appendListener(l *listener.T) {
mu.Lock()
defer mu.Unlock()
listeners = append(listeners, l)
}
const errClosing = "use of closed network connection"
// During graceful shutdown, calls to Accept will start returning errors. This
// is inconvenient, since we know these sorts of errors are peaceful, so we
// silently swallow them.
func peacefulError(err error) error {
if atomic.LoadInt32(&closing) == 0 {
return err
}
// Unfortunately Go doesn't really give us a better way to select errors
// than this, so *shrug*.
if oe, ok := err.(*net.OpError); ok {
if oe.Op == "accept" && oe.Err.Error() == errClosing {
return nil
}
}
return err
}

+ 82
- 0
graceful/server.go View File

@ -0,0 +1,82 @@
package graceful
import (
"crypto/tls"
"net"
"net/http"
)
// Most of the code here is lifted straight from net/http
// Type Server is exactly the same as an http.Server, but provides more graceful
// implementations of its methods.
type Server http.Server
func (srv *Server) ListenAndServe() error {
addr := srv.Addr
if addr == "" {
addr = ":http"
}
l, e := net.Listen("tcp", addr)
if e != nil {
return e
}
return srv.Serve(l)
}
// Unlike the method of the same name on http.Server, this function defaults to
// enforcing TLS 1.0 or higher in order to address the POODLE vulnerability.
// Users who wish to enable SSLv3 must do so by supplying a TLSConfig
// explicitly.
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
addr := srv.Addr
if addr == "" {
addr = ":https"
}
config := &tls.Config{
MinVersion: tls.VersionTLS10,
}
if srv.TLSConfig != nil {
*config = *srv.TLSConfig
}
if config.NextProtos == nil {
config.NextProtos = []string{"http/1.1"}
}
var err error
config.Certificates = make([]tls.Certificate, 1)
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return err
}
conn, err := net.Listen("tcp", addr)
if err != nil {
return err
}
tlsListener := tls.NewListener(conn, config)
return srv.Serve(tlsListener)
}
// ListenAndServe behaves exactly like the net/http function of the same name.
func ListenAndServe(addr string, handler http.Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
// ListenAndServeTLS behaves almost exactly like the net/http function of the
// same name. Unlike net/http, however, this function defaults to enforcing TLS
// 1.0 or higher in order to address the POODLE vulnerability. Users who wish to
// enable SSLv3 must do so by explicitly instantiating a server with an
// appropriately configured TLSConfig property.
func ListenAndServeTLS(addr, certfile, keyfile string, handler http.Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServeTLS(certfile, keyfile)
}
// Serve behaves exactly like the net/http function of the same name.
func Serve(l net.Listener, handler http.Handler) error {
server := &Server{Handler: handler}
return server.Serve(l)
}

+ 0
- 27
graceful/signal.go View File

@ -1,7 +1,6 @@
package graceful
import (
"net"
"os"
"os/signal"
"sync"
@ -117,29 +116,3 @@ func waitForSignal() {
func Wait() {
<-wait
}
func appendListener(l *listener.T) {
mu.Lock()
defer mu.Unlock()
listeners = append(listeners, l)
}
const errClosing = "use of closed network connection"
// During graceful shutdown, calls to Accept will start returning errors. This
// is inconvenient, since we know these sorts of errors are peaceful, so we
// silently swallow them.
func peacefulError(err error) error {
if atomic.LoadInt32(&closing) == 0 {
return err
}
// Unfortunately Go doesn't really give us a better way to select errors
// than this, so *shrug*.
if oe, ok := err.(*net.OpError); ok {
if oe.Op == "accept" && oe.Err.Error() == errClosing {
return nil
}
}
return err
}

Loading…
Cancel
Save