func (sg *SpdyGun) Connect(results chan<- Sample) { sg.Close() connectStart := time.Now() config := tls.Config{ InsecureSkipVerify: true, NextProtos: []string{"spdy/3.1"}, } conn, err := tls.Dial("tcp", sg.target, &config) if err != nil { log.Printf("client: dial: %s\n", err) return } sg.client, err = spdy.NewClientConn(conn) if err != nil { log.Printf("client: connect: %s\n", err) return } ss := &SpdySample{ts: float64(connectStart.UnixNano()) / 1e9, tag: "CONNECT"} ss.rt = int(time.Since(connectStart).Seconds() * 1e6) ss.err = err if ss.err == nil { ss.StatusCode = 200 } results <- ss }
func (sg *SpdyGun) Connect() error { // FIXME: rewrite connection logic, it isn't thread safe right now. start := time.Now() ss := aggregate.AcquireSample(float64(start.UnixNano())/1e9, "CONNECT") defer func() { ss.RT = int(time.Since(start).Seconds() * 1e6) sg.results <- ss }() config := tls.Config{ InsecureSkipVerify: true, NextProtos: []string{"spdy/3.1"}, } conn, err := tls.Dial("tcp", sg.target, &config) if err != nil { ss.Err = err ss.NetCode = 999 return err } client, err := spdy.NewClientConn(conn) if err != nil { ss.Err = err ss.NetCode = 999 return err } else { ss.ProtoCode = 200 } if sg.client != nil { sg.Close() } sg.client = client return nil }
func (sg *SpdyGun) connect(results chan<- aggregate.Sample) error { // FIXME: rewrite connection logic, it isn't thread safe right now. connectStart := time.Now() config := tls.Config{ InsecureSkipVerify: true, NextProtos: []string{"spdy/3.1"}, } conn, err := tls.Dial("tcp", sg.target, &config) if err != nil { return fmt.Errorf("client: dial: %s\n", err) } client, err := spdy.NewClientConn(conn) if err != nil { return fmt.Errorf("client: connect: %v\n", err) } if sg.client != nil { sg.Close() } sg.client = client ss := &SpdySample{ts: float64(connectStart.UnixNano()) / 1e9, tag: "CONNECT"} ss.rt = int(time.Since(connectStart).Seconds() * 1e6) ss.err = err if ss.err == nil { ss.StatusCode = 200 } results <- ss return nil }
func main() { cert, err := tls.LoadX509KeyPair("client.pem", "client.key") if err != nil { fmt.Printf("server: loadkeys: %s", err) } config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true, NextProtos: []string{"spdy/3"}} conn, err := tls.Dial("tcp", "127.0.0.1:4040", &config) if err != nil { fmt.Printf("client: dial: %s", err) } client, err := spdy.NewClientConn(conn) handle(err) req, err := http.NewRequest("GET", "http://localhost:4040/", nil) handle(err) res, err := client.Do(req) handle(err) data := make([]byte, int(res.ContentLength)) _, err = res.Body.(io.Reader).Read(data) fmt.Println(string(data)) res.Body.Close() }
// test tests a site to see if it supports various protocols func (s *site) test(l *os.File) { // Check the name resolves, give up if it does not s.resolves.ran = true _, err := net.LookupHost(s.name) if err != nil { s.logf(l, "Error resolving name: %s", err) s.resolves.yesno = false return } s.resolves.yesno = true // See if port 443 is open, give up if it is not hostPort := net.JoinHostPort(s.name, "443") s.port443Open.ran = true c, err := net.DialTimeout("tcp", hostPort, 2*time.Second) if err != nil { s.logf(l, "TCP dial to port 443 failed: %s", err) s.port443Open.yesno = false return } c.Close() s.port443Open.yesno = true // See if TLS works and if SPDY/3.1 or HTTP/2 offered. Give up if // TLS does not work. If the name doesn't work try adding www. to // se if it's a TLS certificate error. s.tlsWorks.ran = true config := &tls.Config{} config.ServerName = s.name timeoutDialer := &net.Dialer{} timeoutDialer.Timeout = 2 * time.Second tc, err := tls.DialWithDialer(timeoutDialer, "tcp", hostPort, config) if err != nil { s.name = "www." + s.name config.ServerName = s.name hostPort = net.JoinHostPort(s.name, "443") tc, err = tls.DialWithDialer(timeoutDialer, "tcp", hostPort, config) if err != nil { s.logf(l, "Error performing TLS connection: %s", err) s.tlsWorks.yesno = false return } } s.tlsWorks.yesno = true // Retrieve the list of NPN offered protocols and check for // spdy/3.1 and h2 cs := tc.ConnectionState() s.npn = cs.OfferedProtocols s.spdyAnnounced.ran = true s.spdyAnnounced.yesno = in(cs.OfferedProtocols, "spdy/3.1") s.http2Announced.ran = true s.http2Announced.yesno = in(cs.OfferedProtocols, "h2") tc.Close() // See if HTTPS works by performing GET / s.httpsWorks.ran = true httpTransport := &http.Transport{} req, _ := http.NewRequest("GET", "https://"+s.name, nil) resp, err := httpTransport.RoundTrip(req) if err != nil { s.logf(l, "HTTP request failed: %s", err) return } if resp != nil && resp.Body != nil { _, _ = ioutil.ReadAll(resp.Body) resp.Body.Close() } httpTransport.CloseIdleConnections() s.httpsWorks.yesno = err == nil // See if SPDY works by doing GET / over SPDY if s.spdyAnnounced.yesno { s.spdyWorks.ran = true conf := &tls.Config{} conf.NextProtos = []string{"spdy/3.1"} spdyC, err := tls.DialWithDialer(timeoutDialer, "tcp", hostPort, conf) if err == nil { spdyC.SetDeadline(time.Now().Add(time.Minute)) defer spdyC.Close() cs = spdyC.ConnectionState() if cs.NegotiatedProtocol != "spdy/3.1" { s.logf(l, "NegotiatedProtocol not spdy/3.1: %s", cs.NegotiatedProtocol) } else { sc, err := spdy.NewClientConn(spdyC) if err == nil { defer sc.Close() req, _ := http.NewRequest("GET", "https://"+s.name, nil) resp, err := sc.Do(req) if err != nil { s.logf(l, "Failed to do SPDY request: %s", err) } s.spdyWorks.yesno = err == nil if resp != nil && resp.Body != nil { _, _ = ioutil.ReadAll(resp.Body) resp.Body.Close() } } else { s.logf(l, "Failed create SPDY client connection: %s", err) } } } else { s.logf(l, "Failed to dial port 443 for SPDY: %s", err) } } // See if HTTP/2 works by doing GET / using HTTP/2 if s.http2Announced.yesno { s.http2Works.ran = true conf := &tls.Config{} conf.NextProtos = []string{"h2"} h2C, err := tls.DialWithDialer(timeoutDialer, "tcp", hostPort, conf) if err == nil { h2C.SetDeadline(time.Now().Add(time.Minute)) defer h2C.Close() cs = h2C.ConnectionState() if cs.NegotiatedProtocol != "h2" { s.logf(l, "NegotiatedProtocol not h2: %s", cs.NegotiatedProtocol) } else { h2t := &http2.Transport{} h2c, err := h2t.NewClientConn(h2C) if err == nil { req, _ := http.NewRequest("GET", "https://"+s.name, nil) resp, err := h2c.RoundTrip(req) if err != nil { s.logf(l, "HTTP/2 RoundTrip failed: %s", err) } s.http2Works.yesno = err == nil if resp != nil && resp.Body != nil { _, _ = ioutil.ReadAll(resp.Body) resp.Body.Close() } } else { s.logf(l, "Failed create HTTP/2 client connection: %s", err) } h2t.CloseIdleConnections() } } else { s.logf(l, "Failed to dial port 443 for HTTP/2: %s", err) } } }