in session.go [128:177]
func (s *Session) begin(ctx context.Context) error {
// send Begin to server
begin := &frames.PerformBegin{
NextOutgoingID: 0,
IncomingWindow: s.incomingWindow,
OutgoingWindow: s.outgoingWindow,
HandleMax: s.handleMax,
}
if err := s.txFrameAndWait(ctx, begin); err != nil {
return err
}
// wait for response
fr, err := s.waitForFrame(ctx)
if err != nil {
// if we exit before receiving the ack, our caller will clean up the channel.
// however, it does mean that the peer will now have assigned an outgoing
// channel ID that's not in use.
return err
}
begin, ok := fr.(*frames.PerformBegin)
if !ok {
// this codepath is hard to hit (impossible?). if the response isn't a PerformBegin and we've not
// yet seen the remote channel number, the default clause in conn.connReader will protect us from that.
// if we have seen the remote channel number then it's likely the session.mux for that channel will
// either swallow the frame or blow up in some other way, both causing this call to hang.
// deallocate session on error. we can't call
// s.Close() as the session mux hasn't started yet.
debug.Log(1, "RX (Session %p): unexpected begin response frame %T", s, fr)
s.conn.deleteSession(s)
if err := s.conn.Close(); err != nil {
return err
}
return &ConnError{inner: fmt.Errorf("unexpected begin response: %#v", fr)}
}
if len(begin.Properties) > 0 {
s.peerProperties = map[string]any{}
for k, v := range begin.Properties {
s.peerProperties[string(k)] = v
}
}
// start Session multiplexor
go s.mux(begin)
return nil
}