[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: Notice of disconnection



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.



Ing. Pierangelo Masarati
OpenLDAP Core Team

SysNet s.n.c.
Via Dossi, 8 - 27100 Pavia - ITALIA
http://www.sys-net.it
------------------------------------------
Office:   +39.02.23998309
Mobile:   +39.333.4963172
Email:    pierangelo.masarati@sys-net.it
------------------------------------------