This commit is contained in:
Moto Ishizawa 2016-10-09 11:56:57 +09:00
Родитель cf9e454ebc
Коммит 39af16c4e7
1 изменённых файлов: 91 добавлений и 40 удалений

Просмотреть файл

@ -17,19 +17,74 @@ import (
"github.com/summerwind/h2spec/spec/log"
)
const DefaultWindowSize = 65535
type Conn struct {
net.Conn
Settings map[http2.SettingID]uint32
Closed bool
Verbose bool
Timeout time.Duration
Verbose bool
Closed bool
WindowUpdate bool
WindowSize map[uint32]int
framer *http2.Framer
encoder *hpack.Encoder
encoderBuf *bytes.Buffer
}
func Dial(c *config.Config) (*Conn, error) {
var conn net.Conn
var err error
if c.TLS {
dialer := &net.Dialer{}
dialer.Timeout = c.Timeout
tconn, err := tls.DialWithDialer(dialer, "tcp", c.Addr(), c.TLSConfig())
if err != nil {
return nil, err
}
cs := tconn.ConnectionState()
if !cs.NegotiatedProtocolIsMutual {
return nil, errors.New("Protocol negotiation failed")
}
conn = tconn
} else {
conn, err = net.DialTimeout("tcp", c.Addr(), c.Timeout)
if err != nil {
return nil, err
}
}
settings := map[http2.SettingID]uint32{}
framer := http2.NewFramer(conn, conn)
framer.AllowIllegalWrites = true
var encoderBuf bytes.Buffer
encoder := hpack.NewEncoder(&encoderBuf)
return &Conn{
Conn: conn,
Settings: settings,
Timeout: c.Timeout,
Verbose: c.Verbose,
Closed: false,
WindowUpdate: true,
WindowSize: map[uint32]int{0: DefaultWindowSize},
framer: framer,
encoder: encoder,
encoderBuf: &encoderBuf,
}, nil
}
func (conn *Conn) Handshake() error {
done := make(chan error)
@ -39,7 +94,11 @@ func (conn *Conn) Handshake() error {
local := false
remote := false
conn.framer.WriteSettings()
setting := http2.Setting{
ID: http2.SettingInitialWindowSize,
Val: DefaultWindowSize,
}
conn.framer.WriteSettings(setting)
for !(local && remote) {
f, err := conn.framer.ReadFrame()
@ -185,6 +244,7 @@ func (conn *Conn) WaitEvent() Event {
switch f := f.(type) {
case *http2.DataFrame:
ev = EventDataFrame{*f}
conn.updateWindowSize(f)
case *http2.HeadersFrame:
ev = EventHeadersFrame{*f}
case *http2.PriorityFrame:
@ -212,6 +272,34 @@ func (conn *Conn) WaitEvent() Event {
return ev
}
func (conn *Conn) updateWindowSize(f http2.Frame) {
if !conn.WindowUpdate {
return
}
len := int(f.Header().Length)
streamID := f.Header().StreamID
_, ok := conn.WindowSize[streamID]
if !ok {
conn.WindowSize[streamID] = DefaultWindowSize
}
conn.WindowSize[streamID] -= len
if conn.WindowSize[streamID] <= 0 {
incr := DefaultWindowSize + (conn.WindowSize[streamID] * -1)
conn.WriteWindowUpdate(streamID, uint32(incr))
conn.WindowSize[streamID] += incr
}
conn.WindowSize[0] -= len
if conn.WindowSize[0] <= 0 {
incr := DefaultWindowSize + (conn.WindowSize[0] * -1)
conn.WriteWindowUpdate(0, uint32(incr))
conn.WindowSize[0] += incr
}
}
func (conn *Conn) vlog(ev Event, send bool) {
if conn.Verbose {
if send {
@ -221,40 +309,3 @@ func (conn *Conn) vlog(ev Event, send bool) {
}
}
}
func Dial(c *config.Config) (*Conn, error) {
var conn net.Conn
var err error
if c.TLS {
dialer := &net.Dialer{}
dialer.Timeout = c.Timeout
tconn, err := tls.DialWithDialer(dialer, "tcp", c.Addr(), c.TLSConfig())
if err != nil {
return nil, err
}
cs := tconn.ConnectionState()
if !cs.NegotiatedProtocolIsMutual {
return nil, errors.New("Protocol negotiation failed")
}
conn = tconn
} else {
conn, err = net.DialTimeout("tcp", c.Addr(), c.Timeout)
if err != nil {
return nil, err
}
}
settings := map[http2.SettingID]uint32{}
framer := http2.NewFramer(conn, conn)
framer.AllowIllegalWrites = true
var encoderBuf bytes.Buffer
encoder := hpack.NewEncoder(&encoderBuf)
return &Conn{conn, settings, false, c.Verbose, c.Timeout, framer, encoder, &encoderBuf}, nil
}