func (channel *Channel) exchangeDeclare(method *amqp.ExchangeDeclare) *amqp.AMQPError { var classId, methodId = method.MethodIdentifier() // The client I'm using for testing thought declaring the empty exchange // was OK. Check later // if len(method.Exchange) > 0 && !method.Passive { // var msg = "The empty exchange name is reserved" // channel.channelErrorWithMethod(406, msg, classId, methodId) // return nil // } // Check the name format var err = amqp.CheckExchangeOrQueueName(method.Exchange) if err != nil { return amqp.NewSoftError(406, err.Error(), classId, methodId) } // Declare! var ex, amqpErr = exchange.NewFromMethod(method, false, channel.server.exchangeDeleter) if amqpErr != nil { return amqpErr } tp, err := exchange.ExchangeNameToType(method.Type) if err != nil || tp == exchange.EX_TYPE_HEADERS { return amqp.NewHardError(503, err.Error(), classId, methodId) } existing, hasKey := channel.server.exchanges[ex.Name] if !hasKey && method.Passive { return amqp.NewSoftError(404, "Exchange does not exist", classId, methodId) } if hasKey { // if diskLoad { // panic(fmt.Sprintf("Can't disk load a key that exists: %s", ex.Name)) // } if existing.ExType != ex.ExType { return amqp.NewHardError(530, "Cannot redeclare an exchange with a different type", classId, methodId) } if existing.EquivalentExchanges(ex) { if !method.NoWait { channel.SendMethod(&amqp.ExchangeDeclareOk{}) } return nil } // Not equivalent, error in passive mode if method.Passive { return amqp.NewSoftError(406, "Exchange with this name already exists", classId, methodId) } } if method.Passive { if !method.NoWait { channel.SendMethod(&amqp.ExchangeDeclareOk{}) } return nil } // outside of passive mode you can't create an exchange starting with // amq. if strings.HasPrefix(method.Exchange, "amq.") { return amqp.NewSoftError(403, "Exchange names starting with 'amq.' are reserved", classId, methodId) } err = channel.server.addExchange(ex) if err != nil { return amqp.NewSoftError(500, err.Error(), classId, methodId) } err = ex.Persist(channel.server.db) if err != nil { return amqp.NewSoftError(500, err.Error(), classId, methodId) } if !method.NoWait { channel.SendMethod(&amqp.ExchangeDeclareOk{}) } return nil }
func (channel *Channel) queueDeclare(method *amqp.QueueDeclare) *amqp.AMQPError { var classId, methodId = method.MethodIdentifier() // No name means generate a name if len(method.Queue) == 0 { method.Queue = util.RandomId() } // Check the name format var err = amqp.CheckExchangeOrQueueName(method.Queue) if err != nil { return amqp.NewSoftError(406, err.Error(), classId, methodId) } // If this is a passive request, do the appropriate checks and return if method.Passive { queue, found := channel.conn.server.queues[method.Queue] if found { if !method.NoWait { var qsize = uint32(queue.Len()) var csize = queue.ActiveConsumerCount() channel.SendMethod(&amqp.QueueDeclareOk{method.Queue, qsize, csize}) } channel.lastQueueName = method.Queue return nil } return amqp.NewSoftError(404, "Queue not found", classId, methodId) } // Create the new queue var connId = channel.conn.id if !method.Exclusive { connId = -1 } var queue = queue.NewQueue( method.Queue, method.Durable, method.Exclusive, method.AutoDelete, method.Arguments, connId, channel.server.msgStore, channel.server.queueDeleter, ) // If the new queue exists already, ensure the settings are the same. If it // doesn't, add it and optionally persist it existing, hasKey := channel.server.queues[queue.Name] if hasKey { if existing.ConnId != -1 && existing.ConnId != channel.conn.id { return amqp.NewSoftError(405, "Queue is locked to another connection", classId, methodId) } if !existing.EquivalentQueues(queue) { return amqp.NewSoftError(406, "Queue exists and is not equivalent to existing", classId, methodId) } } else { err = channel.server.addQueue(queue) if err != nil { // pragma: nocover return amqp.NewSoftError(500, "Error creating queue", classId, methodId) } // Persist if queue.Durable { queue.Persist(channel.server.db) } } channel.lastQueueName = method.Queue if !method.NoWait { channel.SendMethod(&amqp.QueueDeclareOk{queue.Name, uint32(0), uint32(0)}) } return nil }