Dovecot Dict Protocol¶
General¶
Dovecot’s dict protocol is a line based protocol between the dict client and server processes. The dict server receives lines containing commands and responds to the client with results. Each line ends with an LF character and the maximum line the client is allowed to send a command is 65536 (64KB of data). There is no maximum length enforced for dict server’s response.
Each command is in format:
<command short name><parameters separated with TAB>
The command short name is a single character and the rest of the line containing the command parameters are followed immediately without any whitespace in between.
The commands available in dict protocol and their corresponding short name is shown in table below.
Command |
Command short name |
---|---|
HELLO |
H |
LOOKUP |
L |
ITERATE |
I |
BEGIN |
B |
COMMIT |
C |
COMMIT_ASYNC |
D |
ROLLBACK |
R |
SET |
S |
UNSET |
U |
ATOMIC_INC |
A |
TIMESTAMP |
T |
The reply from dict server is in the same format.
<result short status>(<optional extra values separated with TAB>)
Result statuses relevant for each command and their corresponding short name explained in each command section. Command parameters and extra result values are tab-escaped using the dovecot’s generic tab-escaping. Escaping is described in more details in Dovecot Authentication Protocol.
After responses to certain commands, an execution duration summary line is also sent to the client containing timestamp information about how long the command took to finish. The commands that trigger this timestamp response are LOOKUP, ITERATE, and COMMIT. Format of this line is as follows:
TAB<start sec>TAB<start usec>TAB<end sec>TAB<end usec>
Where the unix timestamp is <sec>.<usec>
for each pair.
The connection starts by the client sending a HELLO
message. The message
contains the initial handshake information.
C: H<major>TAB<minor>TAB<value type>TAB<obsolete user>TAB<dict name>
Note
Prior to dovecot 2.3.17 user was included in the initial handshake but it’s currently not used and the field is empty.
The server then checks client’s protocol version and can either accept the handshake and proceed to response with OK or reject the HELLO and close the connection.
If the handshake is accepted by server, the optional extra values in the response line contain server’s major and minor protocol versions (tab separated). The client also checks the protocol version and can decide to close the connection if versions do not match.
Currently, dovecot’s client and server check that they support the same major version number. Minor version can be ignored. This document describes protocol major version 3, minor 2 which is supported in dovecot v2.3.17+. In earlier dovecot versions lower protocol versions are used e.g. v2.3.16 protocol major version is 2 and minor is 2.
Other dict commands and their line format is described as follows.
Note
Prior to dovecot 2.3.17 none of the following commands included the username for which the dict operation is performed. Instead, the username from the initial handshake message was used.
LOOKUP command¶
Used to lookup a key value from dict.
C: L<key>TAB<user>
Possible responses include:
result status |
status short name |
meaning |
---|---|---|
OK |
O |
Lookup was performed successfully and there was a single value for the key. Value is then appended to the response line. |
MULTI_OK |
M |
Lookup was performed successfully and there were multiple values for the key. In this case all results are joined together with a tab and then double-escaped so the end result looks like a single value. Client would then need to unescape twice to get the list of values separated by tabs. |
NOTFOUND |
N |
Lookup was performed successfully but no value was found with this key. |
FAIL |
F |
Lookup failed due to an error. A tab-escaped error string is appended to the response line. |
ITERATE command¶
Used to iterate over a key path.
C: I<flags>TAB<max rows>TAB<path>TAB<user>
The iteration flag is a integer with following options, which can be OR
ed
together.
flag |
value |
meaning |
---|---|---|
RECURSE |
0x01 |
Recurse to all the sub-hierarchies |
SORT_BY_KEY |
0x02 |
Sort returned results by key |
SORT_BY_VALUE |
0x04 |
Sort returned results by value |
NO_VALUE |
0x08 |
Don’t return values, only keys |
EXACT_KEY |
0x10 |
Don’t recurse at all. This is basically the same as LOOKUP command but it will return all of the rows instead of only the first one. |
FLAG_ASYNC |
0x20 |
Perform iteration asynchronously |
Possible responses include:
result status |
status short name |
meaning |
---|---|---|
OK |
O |
Iteration was done successfully. Note that for each key-value pair A separate OK status is appended to the response line with the key following immediately and all values associated to it joined with tabs. |
FAIL |
F |
Iteration failed due to an error. A tab-escaped error string is appended to the response line. |
ITER_FINISHED |
|
Iteration completed. This is sent after all key value pairs are added to the response. |
BEGIN command¶
Begins a dict transaction with the given ID.
C: B<id>TAB<user>
Note that transactions commands don’t have replies with the exception of COMMIT. After a transaction is successfully started, transaction operations i.e. SET, UNSET, ATOMIC_INC, and TIMESTAMP can be used.
COMMIT command¶
Commit the transaction corresponding to the given ID.
C: C<transaction id>
Note that the transaction is looked up from the ID so no username is required.
Possible responses include:
result status |
status short name |
meaning |
---|---|---|
OK |
O |
Commit was done successfully and all transaction operations completed. |
NOTFOUND |
N |
Transaction ID specified in the commit was not found. |
WRITE_UNCERTAIN |
W |
The transaction may or may not have succeeded (e.g. a write timeout occurred or the connection to dict backend was closed by the backend server). A tab-escaped error string is appended to the response line. |
FAIL |
F |
Iteration failed due to an error. A tab-escaped error string is appended to the response line. |
COMMIT_ASYNC command¶
Obsolete command to commit the transaction. This hasn’t been used by the dict client since v2.2.24.
C: D<transaction id>
Deprecated since version v2.2.24.
The async commit is currently used by dovecot’s dict client even though it is supported by dict server.
ROLLBACK command¶
Rollback changes made in the transaction.
C: R<transaction id>
SET command¶
Set a value for the given key.
C: S<transaction id>TAB<key>TAB<value>
UNSET command¶
Unset a record in the dictionary given the key.
C: U<transaction id>TAB<key>
ATOMIC_INC command¶
Atomically increment numeric value of a key with the given increment value. Note that the value is changed when transaction is being committed, so it’s not known beforehand what the value will become. The value is updated only if it already exists.
C: A<transaction id>TAB<key>TAB<increment>
TIMESTAMP command¶
Set the unix timestamp for the given transaction. Note that this will set the timestamp for the entire transaction. This must be set before any changes are done and can’t be changed afterwards. Currently only dict-sql with Cassandra backend does anything with this.
C: T<transaction id>TAB<sec>TAB<nsec>