From d83d751789eedaac450d80eac727d6aea6a069ba Mon Sep 17 00:00:00 2001 From: fangdingjun Date: Fri, 6 Jul 2018 19:12:13 +0800 Subject: [PATCH] change tls and http2 library --- handler.go | 19 ++++---------- routers.go | 73 +++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/handler.go b/handler.go index 821ff40..15a6724 100644 --- a/handler.go +++ b/handler.go @@ -2,13 +2,14 @@ package main import ( "fmt" - auth "github.com/fangdingjun/go-http-auth" "io" "log" "net" "net/http" "strings" "time" + + auth "github.com/fangdingjun/go-http-auth" ) // handler process the proxy request first(if enabled) @@ -121,21 +122,11 @@ func (h *handler) handleHTTP(w http.ResponseWriter, r *http.Request) { io.Copy(w, resp.Body) } -type flushWriter struct { - w io.Writer -} - -func (fw flushWriter) Write(buf []byte) (int, error) { - n, err := fw.w.Write(buf) - fw.w.(http.Flusher).Flush() - return n, err -} - func (h *handler) handleCONNECT(w http.ResponseWriter, r *http.Request) { host := r.RequestURI if r.ProtoMajor == 2 { - host = r.URL.Host + host = r.Host } if !strings.Contains(host, ":") { @@ -176,7 +167,7 @@ func (h *handler) handleCONNECT(w http.ResponseWriter, r *http.Request) { defer conn.Close() w.WriteHeader(http.StatusOK) - w.(http.Flusher).Flush() + //w.(http.Flusher).Flush() ch := make(chan int, 2) go func() { @@ -185,7 +176,7 @@ func (h *handler) handleCONNECT(w http.ResponseWriter, r *http.Request) { }() go func() { - io.Copy(flushWriter{w}, conn) + io.Copy(w, conn) ch <- 1 }() diff --git a/routers.go b/routers.go index 1f75f06..85a486a 100644 --- a/routers.go +++ b/routers.go @@ -1,12 +1,7 @@ package main import ( - "crypto/tls" "fmt" - auth "github.com/fangdingjun/go-http-auth" - "github.com/fangdingjun/gofast" - loghandler "github.com/gorilla/handlers" - "github.com/gorilla/mux" "io" "log" "net" @@ -15,9 +10,15 @@ import ( "net/url" "os" "regexp" - "sync" - //"path/filepath" "strings" + "sync" + + "github.com/fangdingjun/gnutls" + auth "github.com/fangdingjun/go-http-auth" + "github.com/fangdingjun/gofast" + nghttp2 "github.com/fangdingjun/nghttp2-go" + loghandler "github.com/gorilla/handlers" + "github.com/gorilla/mux" ) type logwriter struct { @@ -49,7 +50,7 @@ func initRouters(cfg conf) { for _, l := range cfg { router := mux.NewRouter() domains := []string{} - certs := []tls.Certificate{} + certs := []*gnutls.Certificate{} // initial virtual host for _, h := range l.Vhost { @@ -59,7 +60,7 @@ func initRouters(cfg conf) { } domains = append(domains, h2) if h.Cert != "" && h.Key != "" { - if cert, err := tls.LoadX509KeyPair(h.Cert, h.Key); err == nil { + if cert, err := gnutls.LoadX509KeyPair(h.Cert, h.Key); err == nil { certs = append(certs, cert) } else { log.Fatal(err) @@ -128,22 +129,29 @@ func initRouters(cfg conf) { } if len(certs) > 0 { - tlsconfig := &tls.Config{ + tlsconfig := &gnutls.Config{ Certificates: certs, + NextProtos: []string{"h2", "http/1.1"}, } - - tlsconfig.BuildNameToCertificate() - - srv := http.Server{ - Addr: addr, - TLSConfig: tlsconfig, - Handler: loghandler.CombinedLoggingHandler(w, hdlr), - } - log.Printf("listen https on %s", addr) - if err := srv.ListenAndServeTLS("", ""); err != nil { + listener, err := gnutls.Listen("tcp", addr, tlsconfig) + if err != nil { log.Fatal(err) } + handler := loghandler.CombinedLoggingHandler(w, hdlr) + log.Printf("listen https on %s", addr) + go func() { + defer listener.Close() + for { + conn, err := listener.Accept() + if err != nil { + log.Println(err) + break + } + go handleHttpClient(conn, handler) + } + }() + } else { log.Printf("listen http on %s", addr) if err := http.ListenAndServe( @@ -260,3 +268,28 @@ func (m myURLMatch) match(r *http.Request, route *mux.RouteMatch) bool { ret := m.re.MatchString(r.URL.Path) return ret } + +func handleHttpClient(c net.Conn, handler http.Handler) { + tlsconn := c.(*gnutls.Conn) + if err := tlsconn.Handshake(); err != nil { + log.Println(err) + return + } + state := tlsconn.ConnectionState() + if state.NegotiatedProtocol == "h2" { + h2conn, err := nghttp2.NewServerConn(tlsconn, handler) + if err != nil { + log.Println(err) + } + h2conn.Run() + return + } + defer c.Close() + resp := &http.Response{ + StatusCode: http.StatusHTTPVersionNotSupported, + Status: http.StatusText(http.StatusHTTPVersionNotSupported), + ProtoMajor: 1, + ProtoMinor: 1, + } + resp.Write(tlsconn) +}