[rabbitmq-discuss] amqp_login -> AMQP_RESPONSE_NONE (RabbitMQ C Client)

Frank Gönninger frank.goenninger at consequor.de
Wed Feb 17 10:55:16 GMT 2010


Hi Tony,

Am 17.02.2010 um 08:12 schrieb Tony Garnock-Jones:

> Hi Frank,
> 
> Frank Goenninger - Consequor Consulting AG wrote:
>> Being new to RabbitMQ I am using the C client to write an abstraction  
>> layer on top of RabbitMQ. I am trying to do an amqp_login call but  
>> always get a AMQP_RESPONSE_NONE in amqp_rpc_reply.
> 
> That looks like a bug in the library to me.

Thought so, too ;-)

> Looking at the code paths, I
> notice two things:
> 
> 1. I'm ignoring the result of amqp_login_inner(). If there's a reason
>    for that, I've forgotten it!
> 
> 2. Setting aside (1), if the code proceeds to the call to
>    amqp_simple_rpc() in amqp_login(), there seems not to be a path
>    that can avoid setting reply_type to some non-zero value, which
>    makes your AMQP_RESPONSE_NONE result unusual to say the least.
> 
>> Is this normal, i.e. this is NOT an error? Do I get a server error if  
>> the login fails or do I get this AMQP_RESPONSE_NONE if the login fails?
> 
> You ought to get some non-zero reply_type that is not
> AMQP_RESPONSE_NORMAL. AMQP_RESPONSE_NONE is probably a bug in the
> library. Unfortunately, during the login procedure, the server is not
> allowed to tell you the cause of the problem if it decides it is going
> to hang up on you: it will simply drop the connection. So check the
> server's error logs to get a clue as to what is going wrong.
> 
> Can you post the code you're using for connecting to and logging in to
> the broker? It would help in figuring out how you can possibly be seeing
> AMQP_RESPONSE_NONE here.

No problem, here you go: (posting inline here and not as attachment to avoid the list server stripping it):

/* PIB stands for "Process Integration Bridge" - a product 
   we're about to launch.
   
   The "Context" is a central struct that holds all connection
   related info and properties needed to exchange data via RabbitMQ. */

static tPIBAMQPrc nEstablishConnection( tsPIBAMQPContextPtr psContext )
{
  tPIBAMQPrc nRC = PIB_OK;

  amqp_connection_state_t psConnection = NULL;

  psConnection = amqp_new_connection();

  psContext->psPIBAMQPConnection->psConnection = psConnection;
   
  if( psConnection == NULL )
    nRC = PIB_ERR_AMQP_CANNOT_CREATE_CONNECTION;
  else
    psContext->psPIBAMQPConnection->nConnectionState = 
      PIB_AMQP_CONNECTION_STATE_CONNECTION_ESTABLISHED;

  return nRC;
}

static tPIBAMQPrc nCreateSocket( tsPIBAMQPContextPtr psContext )
{
  tPIBAMQPrc nRC      = PIB_OK;
  int        nSockFD  = 0;

  nSockFD = amqp_open_socket( psContext->psPIBAMQPConnection->pcAMQPServerHostname,
                              psContext->psPIBAMQPConnection->nAMQPServerPort );
  if( nSockFD >= 0 )
  {
    amqp_set_sockfd( psContext->psPIBAMQPConnection->psConnection,
                     nSockFD );
    psContext->psPIBAMQPConnection->nConnectionState = 
      PIB_AMQP_CONNECTION_STATE_SOCKET_CREATED;
  }
  else
  {
    nRC = PIB_ERR_AMQP_CANNOT_CREATE_SOCKET;
  }

  return nRC;
}

/* THIS FUNCTION NOW HAS A HACK IN IT TO CIRCUMVENT THE 
   AMQP_RESPONSE_NONE SITUATION ... See SET_BIT ;-) */

static tPIBAMQPrc nLogin( tsPIBAMQPContextPtr psContext )
{
  tPIBAMQPrc nRC                = PIB_OK;
  int        nAMQPIgnoredErrors = 0;
  
  nAMQPIgnoredErrors = gAMQPIgnoredErrors;
  SET_BIT(gAMQPIgnoredErrors,PIB_AMQP_IGNORE_AMQP_RESPONSE_NONE);
  
  amqp_login( psContext->psPIBAMQPConnection->psConnection,
              psContext->psPIBAMQPConnection->pcAMQPVirtualHost,
              psContext->psPIBAMQPConnection->nAMQPChannelMax,
              psContext->psPIBAMQPConnection->nAMQPFrameMax,
              psContext->psPIBAMQPConnection->nAMQPHeartbeat,
              psContext->psPIBAMQPConnection->nAMQPSaslMethod,
              psContext->psPIBAMQPConnection->pcAMQPUser,
              psContext->psPIBAMQPConnection->pcAMQPPassword );

  nRC = nCheckAMQPRpcReply( psContext, amqp_get_rpc_reply(),
                            __FILE__, __LINE__, __func__ );
  if( nRC == PIB_OK )
  {
    psContext->psPIBAMQPConnection->nConnectionState = 
      PIB_AMQP_CONNECTION_STATE_LOGGED_IN;
  }

  gAMQPIgnoredErrors = nAMQPIgnoredErrors;

  return nRC;
}

static tPIBAMQPrc nOpenChannel( tsPIBAMQPContextPtr psContext )
{
  tPIBAMQPrc nRC = PIB_OK;

  (void) amqp_channel_open( psContext->psPIBAMQPConnection->psConnection,
                            psContext->psPIBAMQPConnection->nAMQPChannel );

  nRC = nCheckAMQPRpcReply( psContext,
                            amqp_get_rpc_reply(),
                            __FILE__, __LINE__, __func__ );

  if( nRC != PIB_OK )
  {
    nRC = PIB_ERR_AMQP_CANNOT_OPEN_CHANNEL;

    /* frgo, 2010-01-24: TODO: Log error (idea: funcall callback) */

  }
  else
    psContext->psPIBAMQPConnection->nConnectionState = 
      PIB_AMQP_CONNECTION_STATE_CHANNEL_OPENED;
  
  return nRC;
}

static tPIBAMQPrc nConnect( tsPIBAMQPContextPtr psContext )
{
  tPIBAMQPrc nRC    = PIB_OK;
  int        nState = 0;

  nState = nPIBAMQPConnectionGetConnectionState( psContext );

  while(( nState != PIB_AMQP_CONNECTION_STATE_CHANNEL_OPENED ) && 
        ( nRC == PIB_OK ))
  {
    switch( nState )
    {
      /* Step 1 */
      case PIB_AMQP_CONNECTION_STATE_CLOSED :
   
        nRC = nEstablishConnection( psContext );
        break;;

      /* Step 2 */
      case PIB_AMQP_CONNECTION_STATE_CONNECTION_ESTABLISHED :

        nRC = nCreateSocket( psContext );
        break;;

      /* Step 3 */
      case PIB_AMQP_CONNECTION_STATE_SOCKET_CREATED :

        nRC = nLogin( psContext );
        break;;

      /* Step 4 */
      case PIB_AMQP_CONNECTION_STATE_LOGGED_IN :
       
        nRC = nOpenChannel( psContext );
        break;;

      default:
        nRC = PIB_CRIT_AMQP_SW_ERR_INVALID_CONNECTION_STATE;
        break;;
    }

    if( nRC == PIB_OK )
      nState = nPIBAMQPConnectionGetConnectionState( psContext );
  }

  return nRC;
}

That's it. The nConnect() function walks through the status net in 4 steps until the channel is opened successfully. nLogin() fails with AMQP_RESPONSE_NONE if I don't ignore this special error. Needless to say, everything after this just works. I can publish, consume, whatever.

Thanks for jumping in!

Cheers
  Frank



More information about the rabbitmq-discuss mailing list