github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/server.go (about) 1 // Copyright 2013 Jamie Hall. 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 5 package spdy 6 7 import ( 8 "crypto/tls" 9 "errors" 10 "net" 11 "net/http" 12 "time" 13 14 "github.com/SlyMarbo/spdy/common" 15 "github.com/SlyMarbo/spdy/spdy2" 16 "github.com/SlyMarbo/spdy/spdy3" 17 ) 18 19 // NewServerConn is used to create a SPDY connection, using the given 20 // net.Conn for the underlying connection, and the given http.Server to 21 // configure the request serving. 22 func NewServerConn(conn net.Conn, server *http.Server, version, subversion int) (common.Conn, error) { 23 if conn == nil { 24 return nil, errors.New("Error: Connection initialised with nil net.conn.") 25 } 26 if server == nil { 27 return nil, errors.New("Error: Connection initialised with nil server.") 28 } 29 30 switch version { 31 case 3: 32 return spdy3.NewConn(conn, server, subversion), nil 33 34 case 2: 35 return spdy2.NewConn(conn, server), nil 36 37 default: 38 return nil, errors.New("Error: Unsupported SPDY version.") 39 } 40 } 41 42 // ListenAndServeTLS listens on the TCP network address addr 43 // and then calls Serve with handler to handle requests on 44 // incoming connections. Handler is typically nil, in which 45 // case the DefaultServeMux is used. Additionally, files 46 // containing a certificate and matching private key for the 47 // server must be provided. If the certificate is signed by 48 // a certificate authority, the certFile should be the 49 // concatenation of the server's certificate followed by the 50 // CA's certificate. 51 // 52 // See examples/server/server.go for a simple example server. 53 func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error { 54 npnStrings := npn() 55 server := &http.Server{ 56 Addr: addr, 57 Handler: handler, 58 TLSConfig: &tls.Config{ 59 NextProtos: npnStrings, 60 }, 61 TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)), 62 } 63 64 for _, str := range npnStrings { 65 switch str { 66 case "spdy/2": 67 server.TLSNextProto[str] = spdy2.NextProto 68 case "spdy/3": 69 server.TLSNextProto[str] = spdy3.NextProto 70 case "spdy/3.1": 71 server.TLSNextProto[str] = spdy3.NextProto1 72 } 73 } 74 75 return server.ListenAndServeTLS(certFile, keyFile) 76 } 77 78 // ListenAndServeSpdyOnly listens on the TCP network address addr 79 // and then calls Serve with handler to handle requests on 80 // incoming connections. Handler is typically nil, in which 81 // case the DefaultServeMux is used. Additionally, files 82 // containing a certificate and matching private key for the 83 // server must be provided. If the certificate is signed by 84 // a certificate authority, the certFile should be the 85 // concatenation of the server's certificate followed by the 86 // CA's certificate. 87 // 88 // IMPORTANT NOTE: Unlike spdy.ListenAndServeTLS, this function 89 // will ONLY serve SPDY. HTTPS requests are refused. 90 // 91 // See examples/spdy_only_server/server.go for a simple example server. 92 func ListenAndServeSpdyOnly(addr string, certFile string, keyFile string, handler http.Handler) error { 93 npnStrings := npn() 94 if addr == "" { 95 addr = ":https" 96 } 97 if handler == nil { 98 handler = http.DefaultServeMux 99 } 100 server := &http.Server{ 101 Addr: addr, 102 Handler: handler, 103 TLSConfig: &tls.Config{ 104 NextProtos: npnStrings, 105 Certificates: make([]tls.Certificate, 1), 106 }, 107 TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)), 108 } 109 110 for _, str := range npnStrings { 111 switch str { 112 case "spdy/2": 113 server.TLSNextProto[str] = spdy2.NextProto 114 case "spdy/3": 115 server.TLSNextProto[str] = spdy3.NextProto 116 case "spdy/3.1": 117 server.TLSNextProto[str] = spdy3.NextProto1 118 } 119 } 120 121 var err error 122 123 if certFile != "" || keyFile != "" { 124 var err error 125 server.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) 126 if err != nil { 127 return err 128 } 129 } 130 131 conn, err := net.Listen("tcp", addr) 132 if err != nil { 133 return err 134 } 135 136 tlsListener := tls.NewListener(conn, server.TLSConfig) 137 defer tlsListener.Close() 138 139 // Main loop 140 var tempDelay time.Duration 141 for { 142 rw, e := tlsListener.Accept() 143 if e != nil { 144 if ne, ok := e.(net.Error); ok && ne.Temporary() { 145 if tempDelay == 0 { 146 tempDelay = 5 * time.Millisecond 147 } else { 148 tempDelay *= 2 149 } 150 if max := 1 * time.Second; tempDelay > max { 151 tempDelay = max 152 } 153 log.Printf("Accept error: %v; retrying in %v", e, tempDelay) 154 time.Sleep(tempDelay) 155 continue 156 } 157 return e 158 } 159 tempDelay = 0 160 go serveSPDY(rw, server) 161 } 162 } 163 164 // ListenAndServeSPDYNoNPN creates a server that listens exclusively 165 // for SPDY and (unlike the rest of the package) will not support 166 // HTTPS. 167 func ListenAndServeSPDYNoNPN(addr string, certFile string, keyFile string, handler http.Handler, version, subversion int) error { 168 if addr == "" { 169 addr = ":https" 170 } 171 if handler == nil { 172 handler = http.DefaultServeMux 173 } 174 server := &http.Server{ 175 Addr: addr, 176 Handler: handler, 177 TLSConfig: &tls.Config{ 178 Certificates: make([]tls.Certificate, 1), 179 }, 180 } 181 182 var err error 183 server.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) 184 if err != nil { 185 return err 186 } 187 188 conn, err := net.Listen("tcp", addr) 189 if err != nil { 190 return err 191 } 192 193 tlsListener := tls.NewListener(conn, server.TLSConfig) 194 defer tlsListener.Close() 195 196 // Main loop 197 var tempDelay time.Duration 198 for { 199 rw, e := tlsListener.Accept() 200 if e != nil { 201 if ne, ok := e.(net.Error); ok && ne.Temporary() { 202 if tempDelay == 0 { 203 tempDelay = 5 * time.Millisecond 204 } else { 205 tempDelay *= 2 206 } 207 if max := 1 * time.Second; tempDelay > max { 208 tempDelay = max 209 } 210 log.Printf("Accept error: %v; retrying in %v", e, tempDelay) 211 time.Sleep(tempDelay) 212 continue 213 } 214 return e 215 } 216 tempDelay = 0 217 go serveSPDYNoNPN(rw, server, version, subversion) 218 } 219 } 220 221 func serveSPDY(conn net.Conn, srv *http.Server) { 222 defer common.Recover() 223 224 tlsConn, ok := conn.(*tls.Conn) 225 if !ok { // Only allow TLS connections. 226 return 227 } 228 229 if d := srv.ReadTimeout; d != 0 { 230 conn.SetReadDeadline(time.Now().Add(d)) 231 } 232 if d := srv.WriteTimeout; d != 0 { 233 conn.SetWriteDeadline(time.Now().Add(d)) 234 } 235 if err := tlsConn.Handshake(); err != nil { 236 return 237 } 238 239 tlsState := new(tls.ConnectionState) 240 *tlsState = tlsConn.ConnectionState() 241 proto := tlsState.NegotiatedProtocol 242 if fn := srv.TLSNextProto[proto]; fn != nil { 243 fn(srv, tlsConn, nil) 244 } 245 return 246 } 247 248 func serveSPDYNoNPN(conn net.Conn, srv *http.Server, version, subversion int) { 249 defer common.Recover() 250 251 tlsConn, ok := conn.(*tls.Conn) 252 if !ok { // Only allow TLS connections. 253 return 254 } 255 256 if d := srv.ReadTimeout; d != 0 { 257 conn.SetReadDeadline(time.Now().Add(d)) 258 } 259 if d := srv.WriteTimeout; d != 0 { 260 conn.SetWriteDeadline(time.Now().Add(d)) 261 } 262 if err := tlsConn.Handshake(); err != nil { 263 return 264 } 265 266 serverConn, err := NewServerConn(tlsConn, srv, version, subversion) 267 if err != nil { 268 log.Println(err) 269 return 270 } 271 serverConn.Run() 272 }