Hi,
I'm trying to use the new LDAP_OPT_CONNECT_ASYNC with OpenLDAP 2.4.23 client and I can't see how it can be done.
After creating the connection structure via ldap_initialize() I then call ldap_sasl_bind() to do the bind. That calls down to ldap_new_connection() (ldap_sasl_bind -> ldap_send_initial_request -> ldap_open_defconn -> ldap_new_connection) and that implements the asynchronous connect, setting the lconn_status to LDAP_CONNST_CONNECTING and not calling ldap_int_poll() in ldap_pvt_connect().
So far so good. But ldap_send_initial_request() then gets a good return code from ldap_open_defconn(), and so it goes on to call ldap_send_server_request() to send the bind, and that then calls ldap_int_poll() which waits for the connect to complete, making the whole operation synchronous.
It seems to me that for this to work asynchronously, either:
1. ldap_send_initial_request() should check for lconn_status to LDAP_CONNST_CONNECTING on return from ldap_open_defconn(), and if it is then return, probably with error LDAP_X_CONNECTING. It should then be possible to re-call ldap_sasl_bind() when the connect has completed.
2. Establish the connection via ldap_new_connection() before calling ldap_sasl_bind(). But the functions to do that don't appear to be available on the API. ldap_open() could have probably done it, but it is now deprecated. So this would appear to require a new API function that would simply call ldap_open_defconn() and return LDAP_X_CONNECTING.
Or is there some other way to achieve this?
Ian
Ian Puleston wrote:
Hi,
I'm trying to use the new LDAP_OPT_CONNECT_ASYNC with OpenLDAP 2.4.23 client and I can't see how it can be done.
After creating the connection structure via ldap_initialize() I then call ldap_sasl_bind() to do the bind. That calls down to ldap_new_connection() (ldap_sasl_bind -> ldap_send_initial_request -> ldap_open_defconn -> ldap_new_connection) and that implements the asynchronous connect, setting the lconn_status to LDAP_CONNST_CONNECTING and not calling ldap_int_poll() in ldap_pvt_connect().
So far so good. But ldap_send_initial_request() then gets a good return code from ldap_open_defconn(), and so it goes on to call ldap_send_server_request() to send the bind, and that then calls ldap_int_poll() which waits for the connect to complete, making the whole operation synchronous.
It seems to me that for this to work asynchronously, either:
ldap_send_initial_request() should check for lconn_status to LDAP_CONNST_CONNECTING on return from ldap_open_defconn(), and if it is then return, probably with error LDAP_X_CONNECTING. It should then be possible to re-call ldap_sasl_bind() when the connect has completed.
Establish the connection via ldap_new_connection() before calling ldap_sasl_bind(). But the functions to do that don't appear to be available on the API. ldap_open() could have probably done it, but it is now deprecated. So this would appear to require a new API function that would simply call ldap_open_defconn() and return LDAP_X_CONNECTING.
Or is there some other way to achieve this?
Since ldap_open_defconn() is not named ldap_int_xxx or ldap_pvt_xxx I'd guess you should just use that. Another alternative is to simply use your own code to create a connection, and call ldap_init_fd() when you're ready.
Hi,
I'm trying to use the new LDAP_OPT_CONNECT_ASYNC with OpenLDAP 2.4.23 client and I can't see how it can be done.
After creating the connection structure via ldap_initialize() I then call ldap_sasl_bind() to do the bind. That calls down to ldap_new_connection() (ldap_sasl_bind -> ldap_send_initial_request -> ldap_open_defconn -> ldap_new_connection) and that implements the asynchronous connect, setting the lconn_status to LDAP_CONNST_CONNECTING and not calling ldap_int_poll() in ldap_pvt_connect().
So far so good. But ldap_send_initial_request() then gets a good return code from ldap_open_defconn(), and so it goes on to call ldap_send_server_request() to send the bind, and that then calls ldap_int_poll() which waits for the connect to complete, making the whole operation synchronous.
No. ldap_int_poll() will return -2 if timeout is 0 and the filedes was not active. So ldap_send_server_request() will return LDAP_X_CONNECTING if async. The only place where this is used is in back-meta, where searches to multiple handles were initiated sequentially, and LDAP_OPT_CONNECT_ASYNC was introduced to avoid having to wait for each connection to be established before starting processing available results. Now each target independently connects/binds/sends search request asynchronously, and the main loop waits for the most recent event (bind response, search responses) and starts the following one accordingly.
p.
It seems to me that for this to work asynchronously, either:
- ldap_send_initial_request() should check for lconn_status to
LDAP_CONNST_CONNECTING on return from ldap_open_defconn(), and if it is then return, probably with error LDAP_X_CONNECTING. It should then be possible to re-call ldap_sasl_bind() when the connect has completed.
- Establish the connection via ldap_new_connection() before calling
ldap_sasl_bind(). But the functions to do that don't appear to be available on the API. ldap_open() could have probably done it, but it is now deprecated. So this would appear to require a new API function that would simply call ldap_open_defconn() and return LDAP_X_CONNECTING.
Or is there some other way to achieve this?
Ian
-----Original Message----- From: masarati@aero.polimi.it [mailto:masarati@aero.polimi.it] Sent: Thursday, February 03, 2011 9:35 PM
But ldap_send_initial_request() then gets a good return
code from ldap_open_defconn(), and so it goes on to call ldap_send_server_request() to send the bind, and that then calls ldap_int_poll() which waits for the connect to complete, making the
whole operation synchronous.
No. ldap_int_poll() will return -2 if timeout is 0 and the filedes was not active. So ldap_send_server_request() will return LDAP_X_CONNECTING if async.
Thanks. That's what the code should be doing but it's not what I was seeing, so I did a bit of debugging and it turns out that that ldap_int_poll call returns 0, not -2. But that is because the poll (or select) call in it returns 1 indicating that the connect completed immediately. So it's actually functioning as it should.
The only place where this is used is in back-meta, where searches to multiple handles were initiated sequentially, and LDAP_OPT_CONNECT_ASYNC was introduced to avoid having to wait for each connection to be established before starting processing available results.
That's basically exactly the exact reason I am trying to use it now.
Thanks Ian
-----Original Message----- From: masarati@aero.polimi.it [mailto:masarati@aero.polimi.it] Sent: Thursday, February 03, 2011 9:35 PM
ldap_int_poll() will return -2 if timeout is 0 and the filedes was not active. So ldap_send_server_request() will return LDAP_X_CONNECTING if async.
I've hit a new problem with this which I'm pretty sure is a bug (or else an unsupported case) which is that LDAP_OPT_CONNECT_ASYNC doesn't work with TLS connections. It is a timing issue so it may work fine in some implementations, and in fact it works fine for me every time if I have any debug output turned on.
The problem is that ldap_int_tls_connect fails, and I'm pretty sure that it fails because it tries to start the TLS handshake before the connect has completed. Adding just one printf at the start of ldap_int_tls_connect delays it enough that it then works OK every time, presumably because the connect then completes first.
I'm working on a fix now, and I think what is needed is:
1. A call to ldap_int_poll in ldap_int_tls_start if async. Then it should abort without calling ldap_int_tls_connect if not ready (probably return LDAP_X_CONNECTING).
2. In ldap_send_initial_request don't call ldap_send_server_request if lconn_status is LDAP_CONNST_CONNECTING and using TLS (since TLS needs to be started first). Instead return LDAP_X_CONNECTING.
3. Probably something similar to #1 for the case where ldap_start_tls_s is called from ldap_new_connection.
If this all works I'll put in a bug report with a patch.
Ian
Ian Puleston wrote:
-----Original Message----- From: masarati@aero.polimi.it [mailto:masarati@aero.polimi.it] Sent: Thursday, February 03, 2011 9:35 PM
ldap_int_poll() will return -2 if timeout is 0 and the filedes was not active. So ldap_send_server_request() will return LDAP_X_CONNECTING if async.
I've hit a new problem with this which I'm pretty sure is a bug (or else an unsupported case) which is that LDAP_OPT_CONNECT_ASYNC doesn't work with TLS connections. It is a timing issue so it may work fine in some implementations, and in fact it works fine for me every time if I have any debug output turned on.
The problem is that ldap_int_tls_connect fails, and I'm pretty sure that it fails because it tries to start the TLS handshake before the connect has completed. Adding just one printf at the start of ldap_int_tls_connect delays it enough that it then works OK every time, presumably because the connect then completes first.
I'm working on a fix now, and I think what is needed is:
A call to ldap_int_poll in ldap_int_tls_start if async. Then it should abort without calling ldap_int_tls_connect if not ready (probably return LDAP_X_CONNECTING).
In ldap_send_initial_request don't call ldap_send_server_request if lconn_status is LDAP_CONNST_CONNECTING and using TLS (since TLS needs to be started first). Instead return LDAP_X_CONNECTING.
Probably something similar to #1 for the case where ldap_start_tls_s is called from ldap_new_connection.
If this all works I'll put in a bug report with a patch.
Sounds to me like you should just file the bug report first. The patch can come later. Also I don't believe the proper fix should touch so many places. All you should need is to fix the caller of ldap_int_tls_connect(), and as that's a static function there is only one place to fix.
Hi Howard,
-----Original Message----- From: Howard Chu [mailto:hyc@symas.com]
Ian Puleston wrote:
I'm working on a fix now, and I think what is needed is:
- A call to ldap_int_poll in ldap_int_tls_start if async. Then it
should abort without calling ldap_int_tls_connect if not ready (probably return LDAP_X_CONNECTING).
- In ldap_send_initial_request don't call ldap_send_server_request
if lconn_status is LDAP_CONNST_CONNECTING and using TLS (since TLS needs to be started first). Instead return LDAP_X_CONNECTING.
- Probably something similar to #1 for the case where
ldap_start_tls_s is called from ldap_new_connection.
If this all works I'll put in a bug report with a patch.
Sounds to me like you should just file the bug report first. The patch can come later.
I need to get this fixed in the port I am using so I will do that and attach the patch to the bug report. The relevant openldap developers can then choose whether to use that patch as-is or work out something different, and if the latter I can replace the fix in my port with it when it gets released.
Also I don't believe the proper fix should touch so many places. All you should need is to fix the caller of ldap_int_tls_connect(), and as that's a static function there is only one place to fix.
ldap_int_open_connection calls ldap_connect_to_host and then ldap_start_tls_s, so to prevent the latter calling ldap_int_connect after ldap_connect_to_host has returned -2 it will have to be in either ldap_int_open_connection or ldap_start_tls_s. But ldap_int_open_connection probably is a better place than in ldap_int_tls_start.
But we then still have to stop ldap_send_server_request getting called since tls has not started, so that will require a change in ldap_send_initial_request too.
Below is a diagram of the calls involved that I put together when analyzing what was happening here (hopefully email won't munge it too badly). You can see from this that there is no one place that could be modified to prevent both ldap_int_tls_connect and ldap_send_server_request getting called after ldap_pvt_connect has returned -2:
ldap_sasl_bind -> ldap_send_initial_request |-> ldap_open_defconn | -> ldap_new_connection | |-> ldap_int_open_connection | | |-> ldap_connect_to_host | | | -> ldap_pvt_connect | | | -> connect | | | | | -> ldap_int_tls_start | | -> ldap_int_tls_connect | | | |- lconn_status -> LDAP_CONNST_CONNECTING if async. | | | -> ldap_start_tls_s (only if start-tls cmd is to be sent!) | | -> ldap_send_server_request -> ldap_int_poll
For a non-blocking async connect:
- ldap_pvt_connect retrns -2 if EINPROGRESS || EWOULDBLOCK. - ldap_connect_to_host returns the rc returned by ldap_pvt_connect. - ldap_int_open_connection then continues as per success & returns 0. - ldap_new_connection always sets the status to LDAP_CONNST_CONNECTING if async. - ldap_send_server_request returns LDAP_X_CONNECTING if the poll returns -2.
Ian Puleston wrote:
Hi Howard,
-----Original Message----- From: Howard Chu [mailto:hyc@symas.com]
Ian Puleston wrote:
I'm working on a fix now, and I think what is needed is:
- A call to ldap_int_poll in ldap_int_tls_start if async. Then it
should abort without calling ldap_int_tls_connect if not ready (probably return LDAP_X_CONNECTING).
- In ldap_send_initial_request don't call ldap_send_server_request
if lconn_status is LDAP_CONNST_CONNECTING and using TLS (since TLS needs to be started first). Instead return LDAP_X_CONNECTING.
- Probably something similar to #1 for the case where
ldap_start_tls_s is called from ldap_new_connection.
If this all works I'll put in a bug report with a patch.
Sounds to me like you should just file the bug report first. The patch can come later.
I need to get this fixed in the port I am using so I will do that and attach the patch to the bug report. The relevant openldap developers can then choose whether to use that patch as-is or work out something different, and if the latter I can replace the fix in my port with it when it gets released.
You seem to be making the bizarre assumption that only you and other OpenLDAP developers will care. Filing the bug report even before you have the patch allows other people in the community to be alerted and get involved. That is the purpose of an open source community, and the purpose of a public bug tracker.
-----Original Message----- From: Howard Chu [mailto:hyc@symas.com]
Ian Puleston wrote:
If this all works I'll put in a bug report with a patch.
Sounds to me like you should just file the bug report first. The
patch can come later.
I need to get this fixed in the port I am using so I will do that and attach the patch to the bug report.
You seem to be making the bizarre assumption that only you and other OpenLDAP developers will care. Filing the bug report even before you have the patch allows other people in the community to be alerted and get involved.
Sorry, I guess I misunderstood what you were saying - I thought you meant "later" as in "some distant time in the future when we get round to looking at it". I was simply holding off filing the bug report for now in case someone replied to this thread saying it's not a bug.
Filed as bug #6828.
Ian
openldap-technical@openldap.org