TUN-6381: Write error data on QUIC stream when we fail to talk to the origin; separate logging for protocol errors vs. origin errors.

This commit is contained in:
Igor Postelnik 2022-06-13 12:46:52 -05:00
parent 7d0a271000
commit 3da1c25471
2 changed files with 34 additions and 9 deletions

View File

@ -160,7 +160,7 @@ func (q *QUICConnection) handleStream(stream io.ReadWriteCloser) error {
case quicpogs.DataStreamProtocolSignature: case quicpogs.DataStreamProtocolSignature:
reqServerStream, err := quicpogs.NewRequestServerStream(stream, signature) reqServerStream, err := quicpogs.NewRequestServerStream(stream, signature)
if err != nil { if err != nil {
return nil return err
} }
return q.handleDataStream(reqServerStream) return q.handleDataStream(reqServerStream)
case quicpogs.RPCStreamProtocolSignature: case quicpogs.RPCStreamProtocolSignature:
@ -175,30 +175,41 @@ func (q *QUICConnection) handleStream(stream io.ReadWriteCloser) error {
} }
func (q *QUICConnection) handleDataStream(stream *quicpogs.RequestServerStream) error { func (q *QUICConnection) handleDataStream(stream *quicpogs.RequestServerStream) error {
connectRequest, err := stream.ReadConnectRequestData() request, err := stream.ReadConnectRequestData()
if err != nil { if err != nil {
return err return err
} }
if err := q.dispatchRequest(stream, err, request); err != nil {
_ = stream.WriteConnectResponseData(err)
q.logger.Err(err).Str("type", request.Type.String()).Str("dest", request.Dest).Msg("Request failed")
}
return nil
}
func (q *QUICConnection) dispatchRequest(stream *quicpogs.RequestServerStream, err error, request *quicpogs.ConnectRequest) error {
originProxy, err := q.orchestrator.GetOriginProxy() originProxy, err := q.orchestrator.GetOriginProxy()
if err != nil { if err != nil {
return err return err
} }
switch connectRequest.Type { switch request.Type {
case quicpogs.ConnectionTypeHTTP, quicpogs.ConnectionTypeWebsocket: case quicpogs.ConnectionTypeHTTP, quicpogs.ConnectionTypeWebsocket:
tracedReq, err := buildHTTPRequest(connectRequest, stream) tracedReq, err := buildHTTPRequest(request, stream)
if err != nil { if err != nil {
return err return err
} }
w := newHTTPResponseAdapter(stream) w := newHTTPResponseAdapter(stream)
return originProxy.ProxyHTTP(w, tracedReq, connectRequest.Type == quicpogs.ConnectionTypeWebsocket) return originProxy.ProxyHTTP(w, tracedReq, request.Type == quicpogs.ConnectionTypeWebsocket)
case quicpogs.ConnectionTypeTCP: case quicpogs.ConnectionTypeTCP:
rwa := &streamReadWriteAcker{stream} rwa := &streamReadWriteAcker{stream}
metadata := connectRequest.MetadataMap() metadata := request.MetadataMap()
return originProxy.ProxyTCP(context.Background(), rwa, &TCPRequest{Dest: connectRequest.Dest, return originProxy.ProxyTCP(context.Background(), rwa, &TCPRequest{
FlowID: metadata[QUICMetadataFlowID]}) Dest: request.Dest,
FlowID: metadata[QUICMetadataFlowID],
})
} }
return nil return nil
} }

View File

@ -1,6 +1,8 @@
package quic package quic
import ( import (
"fmt"
capnp "zombiezen.com/go/capnproto2" capnp "zombiezen.com/go/capnproto2"
"zombiezen.com/go/capnproto2/pogs" "zombiezen.com/go/capnproto2/pogs"
@ -16,6 +18,18 @@ const (
ConnectionTypeTCP ConnectionTypeTCP
) )
func (c ConnectionType) String() string {
switch c {
case ConnectionTypeHTTP:
return "http"
case ConnectionTypeWebsocket:
return "ws"
case ConnectionTypeTCP:
return "tcp"
}
panic(fmt.Sprintf("invalid ConnectionType: %d", c))
}
// ConnectRequest is the representation of metadata sent at the start of a QUIC application handshake. // ConnectRequest is the representation of metadata sent at the start of a QUIC application handshake.
type ConnectRequest struct { type ConnectRequest struct {
Dest string `capnp:"dest"` Dest string `capnp:"dest"`