Shrink frameWriteMsg, add writeFramer interface, remove empty interfaces.

Just cleanups.
diff --git a/server.go b/server.go
index 82cdb28..27cb220 100644
--- a/server.go
+++ b/server.go
@@ -424,12 +424,12 @@
 // At most one goroutine can be running writeFrameAsync at a time per
 // serverConn.
 func (sc *serverConn) writeFrameAsync(wm frameWriteMsg) {
-	err := wm.write(sc, wm.v)
+	err := wm.write.writeFrame(sc)
 	if ch := wm.done; ch != nil {
 		select {
 		case ch <- err:
 		default:
-			panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.v))
+			panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.write))
 		}
 	}
 	sc.wroteFrameCh <- struct{}{} // tickle frame selection scheduler
@@ -459,8 +459,7 @@
 	sc.vlogf("HTTP/2 connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
 
 	sc.writeFrame(frameWriteMsg{
-		write: writeSettings,
-		v: []Setting{
+		write: writeSettings{
 			{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
 			{SettingMaxConcurrentStreams, sc.advMaxStreams},
 			/* TODO: more actual settings */
@@ -533,10 +532,10 @@
 	}
 }
 
-// writeData writes the data described in req to stream.id.
+// writeDataFromHandler writes the data described in req to stream.id.
 //
 // The provided ch is used to avoid allocating new channels for each
-// write operation.  It's expected that the caller reuses req and ch
+// write operation. It's expected that the caller reuses writeData and ch
 // over time.
 //
 // The flow control currently happens in the Handler where it waits
@@ -545,14 +544,11 @@
 // change when priority is implemented, so the serve goroutine knows
 // the total amount of bytes waiting to be sent and can can have more
 // scheduling decisions available.
-func (sc *serverConn) writeData(stream *stream, data *dataWriteParams, ch chan error) error {
+func (sc *serverConn) writeDataFromHandler(stream *stream, writeData *writeData, ch chan error) error {
 	sc.writeFrameFromHandler(frameWriteMsg{
-		write:     writeDataFrame,
-		cost:      uint32(len(data.p)),
-		stream:    stream,
-		endStream: data.end,
-		v:         data,
-		done:      ch,
+		write:  writeData,
+		stream: stream,
+		done:   ch,
 	})
 	select {
 	case err := <-ch:
@@ -620,9 +616,9 @@
 
 	sc.writingFrame = true
 	sc.needsFrameFlush = true
-	if wm.endStream {
+	if endsStream(wm.write) {
 		if st == nil {
-			panic("nil stream with endStream set")
+			panic("internal error: expecting non-nil stream")
 		}
 		switch st.state {
 		case stateOpen:
@@ -654,8 +650,7 @@
 	if sc.needToSendGoAway {
 		sc.needToSendGoAway = false
 		sc.startFrameWrite(frameWriteMsg{
-			write: writeGoAwayFrame,
-			v: &goAwayParams{
+			write: &writeGoAway{
 				maxStreamID: sc.maxStreamID,
 				code:        sc.goAwayCode,
 			},
@@ -663,7 +658,7 @@
 		return
 	}
 	if sc.writeSched.empty() && sc.needsFrameFlush {
-		sc.startFrameWrite(frameWriteMsg{write: flushFrameWriter})
+		sc.startFrameWrite(frameWriteMsg{write: flushFrameWriter{}})
 		sc.needsFrameFlush = false // after startFrameWrite, since it sets this true
 		return
 	}
@@ -673,7 +668,7 @@
 	}
 	if sc.needToSendSettingsAck {
 		sc.needToSendSettingsAck = false
-		sc.startFrameWrite(frameWriteMsg{write: writeSettingsAck})
+		sc.startFrameWrite(frameWriteMsg{write: writeSettingsAck{}})
 		return
 	}
 	if sc.writeSched.empty() {
@@ -715,10 +710,7 @@
 	if !ok {
 		panic("internal package error; resetStream called on non-existent stream")
 	}
-	sc.writeFrame(frameWriteMsg{
-		write: writeRSTStreamFrame,
-		v:     &se,
-	})
+	sc.writeFrame(frameWriteMsg{write: se})
 	st.sentReset = true
 	sc.closeStream(st, se)
 }
@@ -845,10 +837,7 @@
 		// PROTOCOL_ERROR."
 		return ConnectionError(ErrCodeProtocol)
 	}
-	sc.writeFrame(frameWriteMsg{
-		write: writePingAck,
-		v:     f,
-	})
+	sc.writeFrame(frameWriteMsg{write: writePingAck{f}})
 	return nil
 }
 
@@ -1227,23 +1216,12 @@
 	sc.handler.ServeHTTP(rw, req)
 }
 
-// headerWriteReq is a request to write an HTTP response header from a server Handler.
-type headerWriteReq struct {
-	stream      *stream
-	httpResCode int
-	h           http.Header // may be nil
-	endStream   bool
-
-	contentType   string
-	contentLength string
-}
-
 // called from handler goroutines.
 // h may be nil.
-func (sc *serverConn) writeHeaders(req headerWriteReq, tempCh chan error) {
+func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders, tempCh chan error) {
 	sc.serveG.checkNotOn() // NOT on
 	var errc chan error
-	if req.h != nil {
+	if headerData.h != nil {
 		// If there's a header map (which we don't own), so we have to block on
 		// waiting for this frame to be written, so an http.Flush mid-handler
 		// writes out the correct value of keys, before a handler later potentially
@@ -1251,11 +1229,9 @@
 		errc = tempCh
 	}
 	sc.writeFrameFromHandler(frameWriteMsg{
-		write:     writeHeadersFrame,
-		v:         req,
-		stream:    req.stream,
-		done:      errc,
-		endStream: req.endStream,
+		write:  headerData,
+		stream: st,
+		done:   errc,
 	})
 	if errc != nil {
 		select {
@@ -1271,8 +1247,7 @@
 // called from handler goroutines.
 func (sc *serverConn) write100ContinueHeaders(st *stream) {
 	sc.writeFrameFromHandler(frameWriteMsg{
-		write:  write100ContinueHeadersFrame,
-		v:      st,
+		write:  write100ContinueHeadersFrame{st.id},
 		stream: st,
 	})
 }
@@ -1285,16 +1260,14 @@
 	const maxUint32 = 2147483647
 	for n >= maxUint32 {
 		sc.writeFrameFromHandler(frameWriteMsg{
-			write:  writeWindowUpdate,
-			v:      windowUpdateReq{streamID: st.id, n: maxUint32},
+			write:  writeWindowUpdate{streamID: st.id, n: maxUint32},
 			stream: st,
 		})
 		n -= maxUint32
 	}
 	if n > 0 {
 		sc.writeFrameFromHandler(frameWriteMsg{
-			write:  writeWindowUpdate,
-			v:      windowUpdateReq{streamID: st.id, n: uint32(n)},
+			write:  writeWindowUpdate{streamID: st.id, n: uint32(n)},
 			stream: st,
 		})
 	}
@@ -1363,7 +1336,7 @@
 	wroteHeader   bool        // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
 	sentHeader    bool        // have we sent the header frame?
 	handlerDone   bool        // handler has finished
-	curWrite      dataWriteParams
+	curWrite      writeData
 	frameWriteCh  chan error // re-used whenever we need to block on a frame being written
 
 	closeNotifierMu sync.Mutex // guards closeNotifierCh
@@ -1373,8 +1346,8 @@
 func (rws *responseWriterState) writeData(p []byte, end bool) error {
 	rws.curWrite.streamID = rws.stream.id
 	rws.curWrite.p = p
-	rws.curWrite.end = end
-	return rws.stream.conn.writeData(rws.stream, &rws.curWrite, rws.frameWriteCh)
+	rws.curWrite.endStream = end
+	return rws.stream.conn.writeDataFromHandler(rws.stream, &rws.curWrite, rws.frameWriteCh)
 }
 
 type chunkWriter struct{ rws *responseWriterState }
@@ -1401,8 +1374,8 @@
 			ctype = http.DetectContentType(p)
 		}
 		endStream := rws.handlerDone && len(p) == 0
-		rws.stream.conn.writeHeaders(headerWriteReq{
-			stream:        rws.stream,
+		rws.stream.conn.writeHeaders(rws.stream, &writeResHeaders{
+			streamID:      rws.stream.id,
 			httpResCode:   rws.status,
 			h:             rws.snapHeader,
 			endStream:     endStream,