implement sending of datagrams

This commit is contained in:
Marten Seemann 2019-10-06 20:52:14 +02:00
parent fdaac4f32e
commit 791f896f80
4 changed files with 48 additions and 0 deletions

View file

@ -187,6 +187,10 @@ type Session interface {
// It blocks until the handshake completes.
// Warning: This API should not be considered stable and might change soon.
ConnectionState() ConnectionState
// SendMessage sends a message as a datagram.
// See https://datatracker.ietf.org/doc/draft-pauly-quic-datagram/.
SendMessage([]byte) error
}
// An EarlySession is a session that is handshaking.

View file

@ -210,3 +210,17 @@ func (mr *MockEarlySessionMockRecorder) RemoteAddr() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteAddr", reflect.TypeOf((*MockEarlySession)(nil).RemoteAddr))
}
// SendMessage mocks base method
func (m *MockEarlySession) SendMessage(arg0 []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendMessage", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendMessage indicates an expected call of SendMessage
func (mr *MockEarlySessionMockRecorder) SendMessage(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockEarlySession)(nil).SendMessage), arg0)
}

View file

@ -224,6 +224,20 @@ func (mr *MockQuicSessionMockRecorder) RemoteAddr() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteAddr", reflect.TypeOf((*MockQuicSession)(nil).RemoteAddr))
}
// SendMessage mocks base method
func (m *MockQuicSession) SendMessage(arg0 []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendMessage", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendMessage indicates an expected call of SendMessage
func (mr *MockQuicSessionMockRecorder) SendMessage(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockQuicSession)(nil).SendMessage), arg0)
}
// destroy mocks base method
func (m *MockQuicSession) destroy(arg0 error) {
m.ctrl.T.Helper()

View file

@ -512,6 +512,9 @@ func (s *session) preSetup() {
s.sessionCreationTime = now
s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.connFlowController, s.framer.QueueControlFrame)
if s.config.EnableDatagrams {
s.datagramQueue = newDatagramQueue(s.scheduleSending)
}
}
// run the session main loop
@ -1115,6 +1118,8 @@ func (s *session) handleFrame(f wire.Frame, encLevel protocol.EncryptionLevel, d
err = s.handleRetireConnectionIDFrame(frame, destConnID)
case *wire.HandshakeDoneFrame:
err = s.handleHandshakeDoneFrame()
case *wire.DatagramFrame:
// TODO: handle DATRAGRAM frames
default:
err = fmt.Errorf("unexpected frame type: %s", reflect.ValueOf(&frame).Elem().Type().Name())
}
@ -1739,6 +1744,17 @@ func (s *session) onStreamCompleted(id protocol.StreamID) {
}
}
func (s *session) SendMessage(p []byte) error {
f := &wire.DatagramFrame{DataLenPresent: true}
if protocol.ByteCount(len(p)) > f.MaxDataLen(s.peerParams.MaxDatagramFrameSize, s.version) {
return errors.New("message too large")
}
f.Data = make([]byte, len(p))
copy(f.Data, p)
s.datagramQueue.AddAndWait(f)
return nil
}
func (s *session) LocalAddr() net.Addr {
return s.conn.LocalAddr()
}