Example #1
0
func (conn *http2Connection) makeStream(id uint32) (*HTTP2Stream, error) {
	if conn.isServer {
		if id%2 != 1 || id <= conn.maxStreamID {
			return nil, fmt.Errorf(
				"Server received illegal stream ID %v when maxStreamID is %v",
				id, conn.maxStreamID)
		}
		conn.maxStreamID = id
	}
	flowControl := &inFlow{
		limit:      initialWindowSize,
		connInFlow: conn.flowControl,
	}
	stream := &HTTP2Stream{
		id:            id,
		conn:          conn,
		receiveBuffer: leverutil.NewUnboundedChannel(),
		flowControl:   flowControl,
		sendQuotaPool: newQuotaPool(int(conn.streamSendQuota)),
		shutdownChan:  make(chan struct{}),
	}
	return stream, nil
}
Example #2
0
func newHTTP2Connection(
	isServer bool, netConn net.Conn,
	serverStreamHandler StreamHandler) (*http2Connection, error) {
	var hpackBuffer bytes.Buffer
	writer := bufio.NewWriterSize(netConn, http2IOBufSize)
	conn := &http2Connection{
		isServer:            isServer,
		serverStreamHandler: serverStreamHandler,
		netConn:             netConn,
		writer:              writer,
		framer:              http2.NewFramer(writer, netConn),
		hpackBuffer:         &hpackBuffer,
		hpackEncoder:        hpack.NewEncoder(&hpackBuffer),
		controlBuffer:       leverutil.NewUnboundedChannel(),
		flowControl:         &inFlow{limit: initialConnWindowSize},
		sendQuotaPool:       newQuotaPool(defaultWindowSize),
		writableChan:        make(chan int, 1),
		shutdownChan:        make(chan struct{}),
		closedChan:          make(chan struct{}),
		streamSendQuota:     defaultWindowSize,
		streams:             make(map[uint32]*HTTP2Stream),
	}

	if !isServer {
		conn.nextStreamID = 1 // Odd numbers for client-initiated streams.

		n, err := netConn.Write(clientPreface)
		if err != nil {
			return nil, err
		}
		if n != len(clientPreface) {
			return nil, fmt.Errorf("Preface length mismatch")
		}
	}

	var settings []http2.Setting
	if initialWindowSize != defaultWindowSize {
		settings = append(
			settings,
			http2.Setting{
				ID:  http2.SettingInitialWindowSize,
				Val: uint32(initialWindowSize),
			})
	}
	err := conn.framer.WriteSettings(settings...)
	if err != nil {
		return nil, err
	}
	windowDelta := uint32(initialConnWindowSize - defaultWindowSize)
	if windowDelta > 0 {
		err := conn.framer.WriteWindowUpdate(0, windowDelta)
		if err != nil {
			return nil, err
		}
	}
	conn.writer.Flush()
	conn.writableChan <- 0
	// The controller is responsible with writing frames on the wire.
	go conn.controller()
	// The reader reads in frames from the wire, handles stream 0 /
	// control frames and dispatches frames for the rest of the streams.
	go conn.reader()
	return conn, nil
}