func (c *conn) serveSmart() {
	defer func() {
		if err := recover(); err != nil {
			const size = 4096
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			log.Printf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
		}
		if !c.hijacked() {
			c.close()
		}
	}()

	if tlsConn, ok := c.rwc.(*tls.Conn); ok {
		if d := c.server.ReadTimeout; d != 0 {
			c.rwc.SetReadDeadline(time.Now().Add(d))
		}
		if d := c.server.WriteTimeout; d != 0 {
			c.rwc.SetWriteDeadline(time.Now().Add(d))
		}
		if err := tlsConn.Handshake(); err != nil {
			return
		}
		c.tlsState = new(tls.ConnectionState)
		*c.tlsState = tlsConn.ConnectionState()
		if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) {
			if fn := c.server.TLSNextProto[proto]; fn != nil {
				h := initNPNRequest{tlsConn, serverHandler{c.server}}
				fn(c.server, tlsConn, h)
			}
			return
		}
	}
	initial_bytes := make([]byte, start_bytes)
	// add smart detection
	n, err := c.rwc.Read(initial_bytes)
	if err != nil || n != start_bytes {
		return
	}

	if checkspdy(initial_bytes) {
		s := c.server
		z := new(http.Server)
		z.Addr = s.Addr
		z.Handler = s.inner_h
		z.ReadTimeout = s.ReadTimeout
		z.WriteTimeout = s.WriteTimeout
		z.MaxHeaderBytes = s.MaxHeaderBytes
		server_session := spdy.NewServerSession(NewSmartConn(c.rwc, initial_bytes), z)
		server_session.Serve()
		return
	}

	c2, err := c.server.newConn(NewSmartConn(c.rwc, initial_bytes))
	if err != nil {
		return
	}
	c2.serve()
}
Example #2
0
func main() {

	root := flag.String("r", "./testdata", "root of the directory to serve")
	spdy_debug := flag.Bool("s", false, "enable SPDY debug output")
	flag.Parse()

	if *spdy_debug {
		// enable spdy debug messages
		spdy.EnableDebug()
	}

	for {
		const SLEEP_RETRY = 5
		var conn *tls.Conn
		var err error
		for i := 0; i < 10; i++ {
			// connect to P.
			conn, err = tls.Dial("tcp", HOST_PORT, &tls.Config{InsecureSkipVerify: true})
			if err != nil {
				time.Sleep(100 * time.Millisecond)
			} else {
				break
			}
		}
		if conn == nil {
			log.Println("Failed to connect. Waiting", SLEEP_RETRY, "seconds.")
			time.Sleep(SLEEP_RETRY * time.Second)
			continue
		}

		// build the request
		buf := new(bytes.Buffer)
		_, err = buf.WriteString("Hello from C")
		handle(err)
		req, err := http.NewRequest("PUT", "https://"+HOST_PORT, buf)
		handle(err)

		// make the client connection
		client := httputil.NewClientConn(conn, nil)
		res, err := client.Do(req)
		if err != nil {
			log.Println("Error: Failed to make connection to P:", err)
			continue
		}
		buf.Reset()
		_, err = io.Copy(buf, res.Body)
		handle(err)
		fmt.Printf("%q from P: %q.\n", res.Status, buf.String())

		c, _ := client.Hijack()
		conn = c.(*tls.Conn)
		server := new(http.Server)
		server.Handler = &handler{data: nil, rt: *root}
		//http.FileServer(http.Dir(*root))
		session := spdy.NewServerSession(conn, server)
		session.Serve()
	}
}
func nextproto3(s *Server, c *tls.Conn, h Handler) {
	z := new(http.Server)
	z.Addr = s.Addr
	z.Handler = s.inner_h
	z.ReadTimeout = s.ReadTimeout
	z.WriteTimeout = s.WriteTimeout
	z.MaxHeaderBytes = s.MaxHeaderBytes
	if z.Handler == nil {
		z.Handler = http.DefaultServeMux
	}
	server_session := spdy.NewServerSession(c, z)
	server_session.Serve()
}