-----Original Message-----
From: Pierangelo Masarati [mailto:ando@sys-net.it]
Lars Hesel Christensen XX (AH/LMD) wrote:
> Hi all
>
> I've been looking at the Notice of disconnection handling
in OpenLDAP
> and there is a thing that is confusing me a bit.
>
> in result.c, the function try_read1msg reads data from socket and
> creates a new message from that. If we receive an
unsolicited message,
> e.g, notice of disconnection, then the msgId will be zero,
and we will
> go through the following code(taken from /* $OpenLDAP:
> /libraries/libldap/result.c,v 1.144 2006/12/17 21:04:25
ando Exp $ */):
>
> /* message id */
> if ( ber_get_int( ber, &id ) == LBER_ERROR ) {
> ber_free( ber, 1 );
> ld->ld_errno = LDAP_DECODING_ERROR;
> return( -1 );
> }
>
> /* if it's been abandoned, toss it */
> if ( ldap_abandoned( ld, id, &idx ) ) {
>
> <REMOVED since the msgId is not abandoned>
>
> retry_ber:
> ber_free( ber, 1 );
> if ( ber_sockbuf_ctrl( lc->lconn_sb,
LBER_SB_OPT_DATA_READY, NULL )
> ) {
> goto retry;
> }
> --> return( LDAP_MSG_X_KEEP_LOOKING ); /* continue
> looking */
> }
>
> lr = ldap_find_request_by_msgid( ld, id );
> if ( lr == NULL ) {
> const char *msg = "unknown";
>
> /* the message type */
> tag = ber_peek_tag( ber, &len );
> switch ( tag ) {
> case LBER_ERROR:
> break;
>
> default:
> msg = ldap_int_msgtype2str( tag );
> break;
> }
>
> Debug( LDAP_DEBUG_ANY,
> "no request for response on ld %p msgid
%ld message type %s
> (tossing)\n",
> (void *)ld, (long)id, msg );
>
> goto retry_ber;
> }
>
> Assuming there is no more data to be read from the socket we will
> return in the line marked with the arrow '-->' since
> ldap_find_request_by_msgid() returns NULL.
>
> What confuses me is that later on in try_read1msg we get to (after
> constructing the message:
>
> /* is this the one we're looking for? */
> if ( msgid == LDAP_RES_ANY || id == msgid ) {
> if ( all == LDAP_MSG_ONE
> || ( newmsg->lm_msgtype !=
> LDAP_RES_SEARCH_RESULT
> && newmsg->lm_msgtype !=
> LDAP_RES_SEARCH_ENTRY
> && newmsg->lm_msgtype !=
> LDAP_RES_SEARCH_REFERENCE ) )
> {
> *result = newmsg;
> ld->ld_errno = LDAP_SUCCESS;
> return( tag );
>
> } else if ( newmsg->lm_msgtype ==
> LDAP_RES_SEARCH_RESULT) {
> foundit = 1; /* return the chain later */
> }
> }
>
> Do we have a test case testing notice of disconnection? I tried to
> grep the 'tests' directory for 'notice', 'disconnection'
and 'unsolicited'
> but nothing came up.
>
> Perhaps I'm misunderstanding something here, so if I am I
would very
> much appreciate a hint.
>
Lars,
AFAIK there's no handling, in OpenLDAP's code, of "Notice of
Disconnect". Your analysis is correct, the message will be
ignored since no request can be found for it. Note that
there's no means, right now, to test this condition within
OpenLDAP since its server side implementation never returns
that message. The point, at the client library side, is: how
should this be handled? I mean: if the caller requests
"msgid == LDAP_RES_ANY", then the message can be returned,
and that's it; otherwise, any unsolicited message should not
be queued, but either dealt with by the library, if known, or
ignored. This because, in principle, multiple unsolicited
messages could be returned, and they would share the same msgid (0).
In the case of notice of disconnect, the library could
determine it should no longer expect any message from the
server and, as soon as the client tries to submit a new
request, or asks for response to a pending request, it should
return something like LDAP_UNAVAILABLE or a (yet to be
defined) specific return code.
I think we should discuss details of how this is supposed to
be handled by the client library, since RFC 4511 seems to
give implementors a lot of freedom.
p.
Ok, what really confused me when looking at this is the fact that the
comments for ldap_result (as well as the man pages) claims that we will
receive unsolicited messages when calling ldap_result with LDAP_RES_ANY
or LDAP_RES_UNSOLICITED.
I'm not sure about how to handle unsolicited messages other than notice
of disconnect, but as it is, when the user can just ignore unsolicited
messages, I suppose it would be a good thing if the library itself could
deal with them and dispose of them. I think this is what is intended
when reading the section about unsolicited messages in the RFC. At least
it seems to me that it would be bad/confusing if some unsolicited
messages are handled by the application and some are handled by the
library.
I think it would not be to hard to create a mock-up server that can
accept a new session and then send a notice of disconnection to the
client. That would be a simple way to test that client-side
code/handling of notice of disconnection - whatever the outcome of the
above discussion might be :)
Best regards,
Lars
--
Lars Hesel Christensen
Ericsson Denmark A/S, Telebit
lars.hesel.xx.christensen(a)ericsson.com