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

RE: Notice of disconnection



> -----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@ericsson.com