func (b *broadcaster) queueEnvelopes(srv ab.AtomicBroadcast_BroadcastServer) error { for { select { case <-b.exitChan: return nil default: } msg, err := srv.Recv() if err != nil { return err } payload := &cb.Payload{} err = proto.Unmarshal(msg.Payload, payload) if payload.Header == nil || payload.Header.ChainHeader == nil || payload.Header.ChainHeader.ChainID == "" { logger.Debugf("Received malformed message, dropping connection") return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) } support, ok := b.bs.sm.GetChain(payload.Header.ChainHeader.ChainID) if !ok { // Chain not found, maybe create one? if payload.Header.ChainHeader.Type != int32(cb.HeaderType_CONFIGURATION_TRANSACTION) { err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_NOT_FOUND}) } else { logger.Debugf("Proposing new chain") err = srv.Send(&ab.BroadcastResponse{Status: b.bs.sm.ProposeChain(msg)}) } } else { // Normal transaction for existing chain _, filterErr := support.Filters().Apply(msg) if filterErr != nil { logger.Debugf("Rejecting broadcast message") err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) } else { select { case b.queue <- &msgAndSupport{msg: msg, support: support}: err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS}) default: err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE}) } } } if err != nil { return err } } }
// Broadcast receives a stream of messages from a client for ordering func (b *BackendAB) Broadcast(srv ab.AtomicBroadcast_BroadcastServer) error { for { envelope, err := srv.Recv() if err != nil { return err } if envelope.Payload == nil { err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) if err != nil { return err } } req, err := proto.Marshal(envelope) if err != nil { panic(err) } b.backend.enqueueRequest(req) err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS}) if err != nil { return err } } }