I’ve just deployed the 0.1 version of my custom LDAP server. It was very easy to develop with the OCaml library, and I learnt a bit about LDAP in the process. I had expected it to be more-or-less stateless like HTTP, but in fact it involves a bit more of a conversation, like SMTP. The IETF’s website is refreshingly old-skool… Here’s how it works:
- The client opens a connection and the server acknowledges it, establishing a new session. The is identified as the
bi_op_bind, with which I always send a
`SUCCESS. Binding is marked as optional in this API, I think in fact it is mandatory! You can’t just jump straight into a search, the way you could send an HTTP
GETwith no preamble.
- Next the client sends a
Search_request, my server unpacks it and runs a query against Oracle, reformatting the result set and repacking it as a
- Now the interesting part – the client sends another
Search_request, and maintaining a state per
connection_idso I know this is the second pass, this time I respond with
Search_result_done. Failing to do this appears to send them into an infinite loop until the client times out!
- Finally the client sends a request to unbind, which invokes
bi_op_unbindto clear the state.
This version comes to ~0.15 kLOC, including all the supporting infrastructure such as command line parsing, logging, signal handling, etc, the bulk of the work is done within the framework. My approach was to first implement a stub server that simply logged the queries sent by the clients, then implement a stub client in order to see the responses sent back to those queries from a traditional server. I am not entirely happy with my state machine, it is a
Hashtbl in the scope above the declaration of
connection_id to a
bool, but I can’t think offhand of a better way to maintain the necessary state between search requests (this would have been another good use for a monad).