[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