Ejemplo n.º 1
0
func (channel *Channel) basicRoute(methodFrame amqp.MethodFrame) *amqp.AMQPError {
	switch method := methodFrame.(type) {
	case *amqp.BasicQos:
		return channel.basicQos(method)
	case *amqp.BasicRecover:
		return channel.basicRecover(method)
	case *amqp.BasicNack:
		return channel.basicNack(method)
	case *amqp.BasicConsume:
		return channel.basicConsume(method)
	case *amqp.BasicCancel:
		return channel.basicCancel(method)
	case *amqp.BasicCancelOk:
		return channel.basicCancelOk(method)
	case *amqp.BasicPublish:
		return channel.basicPublish(method)
	case *amqp.BasicGet:
		return channel.basicGet(method)
	case *amqp.BasicAck:
		return channel.basicAck(method)
	case *amqp.BasicReject:
		return channel.basicReject(method)
	}
	var classId, methodId = methodFrame.MethodIdentifier()
	return amqp.NewHardError(540, "Unable to route method frame", classId, methodId)
}
Ejemplo n.º 2
0
func (channel *Channel) exchangeUnbind(method *amqp.ExchangeUnbind) *amqp.AMQPError {
	var classId, methodId = method.MethodIdentifier()
	return amqp.NewHardError(540, "Not implemented", classId, methodId)
	// if !method.NoWait {
	// 	channel.SendMethod(&amqp.ExchangeUnbindOk{})
	// }
}
Ejemplo n.º 3
0
func (channel *Channel) routeMethod(frame *amqp.WireFrame) *amqp.AMQPError {
	var methodReader = bytes.NewReader(frame.Payload)
	var methodFrame, err = amqp.ReadMethod(methodReader, channel.server.strictMode)
	if err != nil {
		return amqp.NewHardError(500, err.Error(), 0, 0)
	}
	var classId, methodId = methodFrame.MethodIdentifier()

	// If the method isn't closing related and we're closing, ignore the frames
	var closeChannel = classId == amqp.ClassIdChannel && (methodId == amqp.MethodIdChannelClose || methodId == amqp.MethodIdChannelCloseOk)
	var closeConnection = classId == amqp.ClassIdConnection && (methodId == amqp.MethodIdConnectionClose || methodId == amqp.MethodIdConnectionCloseOk)
	if channel.state == CH_STATE_CLOSING && !(closeChannel || closeConnection) {
		return nil
	}

	// Non-open method on an INIT-state channel is an error
	if channel.state == CH_STATE_INIT && (classId != 20 || methodId != 10) {
		return amqp.NewHardError(
			503,
			"Non-Channel.Open method called on unopened channel",
			classId,
			methodId,
		)
	}
	// Route
	// fmt.Println("Routing method: " + methodFrame.MethodName())
	switch {
	case classId == 10:
		return channel.connectionRoute(channel.conn, methodFrame)
	case classId == 20:
		return channel.channelRoute(methodFrame)
	case classId == 40:
		return channel.exchangeRoute(methodFrame)
	case classId == 50:
		return channel.queueRoute(methodFrame)
	case classId == 60:
		return channel.basicRoute(methodFrame)
	case classId == 90:
		return channel.txRoute(methodFrame)
	default:
		return amqp.NewHardError(540, "Not implemented", classId, methodId)
	}
	return nil
}
Ejemplo n.º 4
0
func (channel *Channel) txRoute(methodFrame amqp.MethodFrame) *amqp.AMQPError {
	switch method := methodFrame.(type) {
	case *amqp.TxSelect:
		return channel.txSelect(method)
	case *amqp.TxCommit:
		return channel.txCommit(method)
	case *amqp.TxRollback:
		return channel.txRollback(method)
	}
	var classId, methodId = methodFrame.MethodIdentifier()
	return amqp.NewHardError(540, "Unable to route method frame", classId, methodId)
}
Ejemplo n.º 5
0
func (channel *Channel) exchangeRoute(methodFrame amqp.MethodFrame) *amqp.AMQPError {
	switch method := methodFrame.(type) {
	case *amqp.ExchangeDeclare:
		return channel.exchangeDeclare(method)
	case *amqp.ExchangeBind:
		return channel.exchangeBind(method)
	case *amqp.ExchangeUnbind:
		return channel.exchangeUnbind(method)
	case *amqp.ExchangeDelete:
		return channel.exchangeDelete(method)
	}
	var classId, methodId = methodFrame.MethodIdentifier()
	return amqp.NewHardError(540, "Not implemented", classId, methodId)
}
Ejemplo n.º 6
0
func (channel *Channel) handleContentHeader(frame *amqp.WireFrame) *amqp.AMQPError {
	if channel.currentMessage == nil {
		return amqp.NewSoftError(500, "Unexpected content header frame!", 0, 0)
	}
	if channel.currentMessage.Header != nil {
		return amqp.NewSoftError(500, "Unexpected content header frame! Already saw header", 0, 0)
	}
	var headerFrame = &amqp.ContentHeaderFrame{}
	var err = headerFrame.Read(bytes.NewReader(frame.Payload), channel.server.strictMode)
	if err != nil {
		return amqp.NewHardError(500, "Error parsing header frame: "+err.Error(), 0, 0)
	}
	channel.currentMessage.Header = headerFrame
	return nil
}
Ejemplo n.º 7
0
func NewFromMethod(method *amqp.ExchangeDeclare, system bool, exchangeDeleter chan *Exchange) (*Exchange, *amqp.AMQPError) {
	var classId, methodId = method.MethodIdentifier()
	var tp, err = ExchangeNameToType(method.Type)
	if err != nil || tp == EX_TYPE_HEADERS {
		return nil, amqp.NewHardError(503, "Bad exchange type", classId, methodId)
	}
	var ex = NewExchange(
		method.Exchange,
		tp,
		method.Durable,
		method.AutoDelete,
		method.Internal,
		method.Arguments,
		system,
		exchangeDeleter,
	)
	return ex, nil
}
Ejemplo n.º 8
0
func (channel *Channel) addConsumer(q *queue.Queue, method *amqp.BasicConsume) *amqp.AMQPError {
	var classId, methodId = method.MethodIdentifier()
	// Create consumer
	var consumer = consumer.NewConsumer(
		channel.server.msgStore,
		method.Arguments,
		channel,
		method.ConsumerTag,
		method.Exclusive,
		method.NoAck,
		method.NoLocal,
		q,
		q.Name,
		channel.defaultPrefetchSize,
		channel.defaultPrefetchCount,
		channel.conn.id,
	)

	channel.consumerLock.Lock()
	defer channel.consumerLock.Unlock()
	// Make sure the doesn't exist on this channel
	_, found := channel.consumers[consumer.ConsumerTag]
	if found {
		return amqp.NewHardError(
			530,
			fmt.Sprintf("Consumer tag already exists: %s", consumer.ConsumerTag),
			classId,
			methodId,
		)
	}

	// Add the consumer to the queue, then channel
	code, err := q.AddConsumer(consumer, method.Exclusive)
	if err != nil {
		return amqp.NewSoftError(code, err.Error(), classId, methodId)
	}

	channel.consumers[consumer.ConsumerTag] = consumer
	consumer.Start()
	return nil
}
Ejemplo n.º 9
0
func (channel *Channel) connectionRoute(conn *AMQPConnection, methodFrame amqp.MethodFrame) *amqp.AMQPError {
	switch method := methodFrame.(type) {
	case *amqp.ConnectionStartOk:
		return channel.connectionStartOk(conn, method)
	case *amqp.ConnectionTuneOk:
		return channel.connectionTuneOk(conn, method)
	case *amqp.ConnectionOpen:
		return channel.connectionOpen(conn, method)
	case *amqp.ConnectionClose:
		return channel.connectionClose(conn, method)
	case *amqp.ConnectionSecureOk:
		return channel.connectionSecureOk(conn, method)
	case *amqp.ConnectionCloseOk:
		return channel.connectionCloseOk(conn, method)
	case *amqp.ConnectionBlocked:
		return channel.connectionBlocked(conn, method)
	case *amqp.ConnectionUnblocked:
		return channel.connectionUnblocked(conn, method)
	}
	var classId, methodId = methodFrame.MethodIdentifier()
	return amqp.NewHardError(540, "Unable to route method frame", classId, methodId)
}
Ejemplo n.º 10
0
func (channel *Channel) start() {
	if channel.id == 0 {
		channel.state = CH_STATE_OPEN
		go channel.startConnection()
	} else {
		go channel.startChannel()
	}

	// Receive method frames from the client and route them
	go func() {
		for {
			if channel.state == CH_STATE_CLOSED {
				break
			}
			var frame = <-channel.incoming
			var amqpErr *amqp.AMQPError = nil
			switch {
			case frame.FrameType == uint8(amqp.FrameMethod):
				amqpErr = channel.routeMethod(frame)
			case frame.FrameType == uint8(amqp.FrameHeader):
				if channel.state != CH_STATE_CLOSING {
					amqpErr = channel.handleContentHeader(frame)
				}
			case frame.FrameType == uint8(amqp.FrameBody):
				if channel.state != CH_STATE_CLOSING {
					amqpErr = channel.handleContentBody(frame)
				}
			default:
				amqpErr = amqp.NewHardError(500, "Unknown frame type", 0, 0)
			}
			if amqpErr != nil {
				channel.sendError(amqpErr)
			}
		}
	}()
}
Ejemplo n.º 11
0
func (channel *Channel) connectionUnblocked(conn *AMQPConnection, method *amqp.ConnectionUnblocked) *amqp.AMQPError {
	return amqp.NewHardError(540, "Not implemented", 10, 61)
}
Ejemplo n.º 12
0
func (channel *Channel) basicCancelOk(method *amqp.BasicCancelOk) *amqp.AMQPError {
	// TODO(MAY)
	var classId, methodId = method.MethodIdentifier()
	return amqp.NewHardError(540, "Not implemented", classId, methodId)
}
Ejemplo n.º 13
0
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
}