Main Page » Developer Section » Clients » Server Protocol

Server Protocol

This page presents the classes and functions of the BaseX Clients, and the underlying protocol, which is utilized for communicating with the database server. A detailed example demonstrates how a concrete byte exchange can look like.

Workflow

  • All clients are based on the client/server architecture. Hence, a BaseX database server must be started first.
  • Each client provides a session class or script with methods to connect to and communicate with the database server. A socket connection will be established by the constructor, which expects a host, port, username and password as arguments.
  • The execute() method is called to launch a database command. It returns the result or throws an exception with the received error message.
  • The query() method creates a query instance. Variables and the context item can be bound to that instance, and the result can either be requested via execute(), or in an iterative manner with the more() and next() functions. If an error occurs, an exception will be thrown.
  • The create(), add(), put() and putbinary() methods pass on input streams to the corresponding database commands. The input can be a UTF-8 encoded XML document, a binary resource, or any other data (such as JSON or CSV) that can be successfully converted to a resource by the server.
  • To speed up execution, an output stream can be specified by some clients; this way, all results will be directed to that output stream.
  • Most clients are accompanied by some example files, which demonstrate how database commands can be executed or how queries can be evaluated.

Transfer Protocol

All Clients use the following client/server protocol to communicate with the server.

The description of the protocol is helpful if you want to implement your own client.

Conventions

  • \xx: single byte.
  • {...}: utf8 strings or raw data, suffixed with a \00 byte. To avoid confusion with this end-of-string byte, all transferred \00 and \FF bytes are prefixed by an additional \FF byte.

Authentication

Digest

Digest authentication is used since Version 8.0:

  1. Client connects to server socket
  2. Server sends a realm and nonce, separated by a colon: {realm:nonce}
  3. Client sends the username and a hash value. The hash is composed of the md5 hash of:
    1. the md5 hash of the username, realm, and password (all separated by a colon), and
    2. the nonce: {username} {md5(md5(username:realm:password) + nonce)}
  4. Server replies with \00 (success) or \01 (error)

CRAM-MD5

CRAM-MD5 was discarded because unsalted md5 hashes can easily be uncovered using rainbow tables. However, most client bindings still provide support for the outdated handshaking, as it only slightly differs from the new protocol:

  1. Client connects to server socket
  2. Server sends a nonce (timestamp): {nonce}
  3. Client sends the username and a hash value. The hash is composed of the md5 hash of:
    1. the md5 of the password and
    2. the nonce: {username} {md5(md5(password) + nonce)}
  4. Server replies with \00 (success) or \01 (error)

It is possible to support both digest and cram-md5 authentication in clients: If the first server response contains no colon, cram-md5 should be chosen.

Command Protocol

The following byte sequences are sent and received from the client (please note that a specific client may not support all of the presented commands):

Command Client Request Server Response Description
COMMAND {command} {result} {info} \00 Executes a database command.
QUERY \00 {query} {id} \00 Creates a new query instance and returns its id.
CREATE \08 {name} {input} {info} \00 Creates a new database with the specified input (may be empty).
ADD \09 {path} {input} {info} \00 Adds a new document to the opened database.
PUT \0C {path} {input} {info} \00 Puts (adds or replaces) an XML document resource in the opened database.
PUTBINARY \0D {path} {input} {info} \00 Puts (adds or replaces) a binary resource in the opened database.
↯ error { partial result } {error} \01 Error feedback.

Query Command Protocol

Queries are referenced via an id, which has been returned by the QUERY command (see above).

Query Command Client Request Server Response Description
CLOSE \02 {id} \00 \00 Closes and unregisters the query with the specified id.
BIND \03 {id} {name} {value} {type} \00 \00 Binds a value to a variable. The type will be ignored if the string is empty.
RESULTS \04 {id} \xx {item} ... \xx {item} \00 Returns all resulting items as strings, prefixed by a single byte (\xx) that represents the Type ID. This command is called by the more() function of a client implementation.
EXECUTE \05 {id} {result} \00 Executes the query and returns the result as a single string.
INFO \06 {id} {result} \00 Returns a string with query compilation and profiling info.
OPTIONS \07 {id} {result} \00 Returns a string with all query serialization parameters, which can e.g. be assigned to the SERIALIZER option.
CONTEXT \0E {id} {value} {type} \00 \00 Binds a value to the context. The type will be ignored if the string is empty.
UPDATING \1E {id} {result} \00 Returns true if the query contains updating expressions; false otherwise.
FULL \1F {id} XDM {item} ... XDM {item} \00 Returns all resulting items as strings, prefixed by the XDM Metadata. This command is e. g. used by the XQJ API.

As can be seen in the table, all results end with a single \00 byte, which indicates that the process was successful. If an error occurs, an additional byte \01 is sent, which is then followed by the error message string.

Binding Sequences

Also, sequences can be bound to variables and the context:

  • empty-sequence() must be supplied as type if an empty sequence is to be bound.
  • Multiple items are supplied via the {value} argument and separated with \01 bytes.
  • Item types are specified by appending \02 and the type in its string representation to an item. If no item type is specified, the general type is used.

Some examples for the {value} argument:

  • the two integers 123 and 789 are encoded as 123, \01, 789 and \00 (xs:integer may be specified via the {type} argument).
  • the two items xs:integer(123) and xs:string('ABC') are encoded as 123, \02, xs:integer, \01, ABC, \02, xs:string and \00.

Example

In the following example, a client registers a new session and executes the INFO database command. Next, it creates a new query instance for the XQuery expression 1, 2+'3'. The query is then evaluated, and the server returns the result of the first subexpression 1 and an error for the second sub expression. Finally, the query instance and client session are closed.

Operation Bytes sent/received
Client connects to the database server socket
Server sends realm and timestamp BaseX:1369578179679 ◄ 42 61 73 65 58 3A 31 33 36 39 35 37 38 31 37 39 36 37 39 00
Client sends username jack 6A 61 63 6B 00 ►
Client sends hash: md5(md5("jack:BaseX:topsecret") + 1369578179679) = ca664a31f8deda9b71ea3e79347f6666 63 61 36 ... 00 ►
Server replies with success code ◄ 00
Client sends the INFO command 49 4E 46 4F 00 ►
Server responds with the result General Information... ◄ 47 65 6e 65 ... 00
Server additionally sends an (empty) info string ◄ 00
Client creates a new query instance for the XQuery 1, 2+'3' 00 31 2C 20 32 2B 27 33 27 00 ►
Server returns query id "1" and a success code ◄ 31 00 00
Client requests the query results via the RESULTS protocol command and its query id 04 31 00 ►
Server returns the first result (1, type xs:integer) ◄ 52 31 00
Server sends a single \00 byte instead of a new result, which indicates that no more results can be expected ◄ 00
Server sends the error code \01 and the error message (Stopped at...) ◄ 01 53 74 6f ... 00
Client closes the query instance 02 31 00 ►
Server sends a response (which is equal to an empty info string) and success code ◄ 00 00
Client closes the socket connection

Constructors and Functions

Most language bindings provide the following constructors and functions:

Client Sessions
Create a new session Session(String host, int port, String name, String password)
Execute a command String execute(String command)
Create a new query instance Query query(String query)
Create a database with an initial document void create(String name, InputStream input)
Add a document void add(String path, InputStream input)
Add or replace a document void put(String path, InputStream input)
Add or replace a binary resource void putBinary(String path, InputStream input)
Return process information String info()
Close the session void close()
Query Instances
Create new query instance Query(Session session, String query)
Bind a variable void bind(String name, String value, String type)
Bind the context item void context(String value, String type)
Execute the query String execute()
Check if a query returns more items boolean more()
Return the next item String next()
Return query information String info()
Return serialization parameters String options()
Check if the query is updating boolean updating()
Close the query void close()

XDM Metadata

In most cases, the XDM metadata is identical to the Type ID. For the three types document-node(), attribute(), and xs:QName, the ID is followed by an additional {URI} string.

Type IDs

The following table lists the type IDs that are returned by the server. Currently, all node kinds are of type xs:untypedAtomic:

Type ID Node Kind/Item Type Type
7 Function item function
8 node() node
9 text() node
10 processing-instruction() node
11 element() node
12 document-node() node
13 document-node(element()) node
14 attribute() node
15 comment() node
32 item() atomic value
33 xs:untyped atomic value
34 xs:anyType atomic value
35 xs:anySimpleType atomic value
36 xs:anyAtomicType atomic value
37 xs:untypedAtomic atomic value
38 xs:string atomic value
39 xs:normalizedString atomic value
40 xs:token atomic value
41 xs:language atomic value
42 xs:NMTOKEN atomic value
43 xs:Name atomic value
44 xs:NCName atomic value
45 xs:ID atomic value
46 xs:IDREF atomic value
47 xs:ENTITY atomic value
48 xs:float atomic value
49 xs:double atomic value
50 xs:decimal atomic value
51 xs:precisionDecimal atomic value
52 xs:integer atomic value
53 xs:nonPositiveInteger atomic value
54 xs:negativeInteger atomic value
55 xs:long atomic value
56 xs:int atomic value
57 xs:short atomic value
58 xs:byte atomic value
59 xs:nonNegativeInteger atomic value
60 xs:unsignedLong atomic value
61 xs:unsignedInt atomic value
62 xs:unsignedShort atomic value
63 xs:unsignedByte atomic value
64 xs:positiveInteger atomic value
65 xs:duration atomic value
66 xs:yearMonthDuration atomic value
67 xs:dayTimeDuration atomic value
68 xs:dateTime atomic value
69 xs:dateTimeStamp atomic value
70 xs:date atomic value
71 xs:time atomic value
72 xs:gYearMonth atomic value
73 xs:gYear atomic value
74 xs:gMonthDay atomic value
75 xs:gDay atomic value
76 xs:gMonth atomic value
77 xs:boolean atomic value
78 basex:binary atomic value
79 xs:base64Binary atomic value
80 xs:hexBinary atomic value
81 xs:anyURI atomic value
82 xs:QName atomic value
83 xs:NOTATION atomic value

Changelog

Version 8.2
  • Removed: WATCH and UNWATCH command
Version 8.0
  • Updated: cram-md5 replaced with digest authentication
  • Updated: BIND command: support more than one item
Version 7.2
  • Added: Query Commands CONTEXT, UPDATING and FULL
  • Added: Client function context(String value, String type)

⚡Generated with XQuery