|
| 1 | +.. _internals-iproto-format: |
| 2 | + |
| 3 | +Request and response format |
| 4 | +=========================== |
| 5 | + |
| 6 | +The types referred to in this document are `MessagePack <http://MessagePack.org>`_ types. |
| 7 | +For their definitions, see the :ref:`MP_* MessagePack types <box_protocol-notation>` section. |
| 8 | + |
| 9 | +.. _internals-unified_packet_structure: |
| 10 | + |
| 11 | +Packet structure |
| 12 | +---------------- |
| 13 | + |
| 14 | +Requests and responses have similar structure. They contain three sections: size, header, and body. |
| 15 | + |
| 16 | +.. raw:: html |
| 17 | + :file: images/format.svg |
| 18 | + |
| 19 | +It is legal to put more than one request in a packet. |
| 20 | + |
| 21 | +Size |
| 22 | +---- |
| 23 | + |
| 24 | +The size is an MP_UINT -- unsigned integer, usually 32-bit. |
| 25 | +It the size of the header plus the size of the body. |
| 26 | +It may be useful to compare it with the number of bytes remaining in the packet. |
| 27 | + |
| 28 | +.. _box_protocol-header: |
| 29 | + |
| 30 | +Header |
| 31 | +------ |
| 32 | + |
| 33 | +The header is an MP_MAP. It may contain, in any order: |
| 34 | + |
| 35 | +.. raw:: html |
| 36 | + :file: images/header.svg |
| 37 | + |
| 38 | +* Both the request and response make use of the :ref:`IPROTO_REQUEST_TYPE <internals-iproto-keys-request_type>` key. |
| 39 | + It denotes the type of the packet. |
| 40 | + |
| 41 | +* The request and the matching response have the same sync number (:ref:`IPROTO_SYNC <internals-iproto-keys-sync>`). |
| 42 | + |
| 43 | +* :ref:`IPROTO_SCHEMA_VERSION <internals-iproto-keys-schema_version>` is an optional key that indicates |
| 44 | + whether there was a major change in the schema. |
| 45 | + |
| 46 | +* In :ref:`interactive transactions <txn_mode_stream-interactive-transactions>`, |
| 47 | + every stream is identified by a unique :ref:`IPROTO_STREAM_ID <box_protocol-iproto_stream_id>`. |
| 48 | + |
| 49 | +In case of replicating :ref:`synchronous transactions <repl_sync>`, |
| 50 | +the header also contains the :ref:`IPROTO_FLAGS <box_protocol-flags>` key. |
| 51 | + |
| 52 | +Encoding and decoding |
| 53 | +~~~~~~~~~~~~~~~~~~~~~ |
| 54 | + |
| 55 | +To see how Tarantool encodes the header, have a look at file |
| 56 | +`xrow.c <https://github.com/tarantool/tarantool/blob/master/src/box/xrow.c>`_, |
| 57 | +function ``xrow_header_encode``. |
| 58 | + |
| 59 | +To see how Tarantool decodes the header, have a look at file |
| 60 | +`net_box.c <https://github.com/tarantool/tarantool/blob/master/src/box/lua/net_box.c>`__, |
| 61 | +function ``netbox_decode_data``. |
| 62 | + |
| 63 | +For example, in a successful response to ``box.space:select()``, |
| 64 | +the IPROTO_REQUEST_TYPE value will be 0 = ``IPROTO_OK`` and the |
| 65 | +array will have all the tuples of the result. |
| 66 | + |
| 67 | +Read the source code file `net_box.c <https://github.com/tarantool/tarantool/blob/master/src/box/lua/net_box.c>`__ |
| 68 | +where the function ``decode_metadata_optional`` is an example of how Tarantool |
| 69 | +itself decodes extra items. |
| 70 | + |
| 71 | +Body |
| 72 | +---- |
| 73 | + |
| 74 | +The body is an MP_MAP. Maximal iproto package body length is 2 GiB. |
| 75 | + |
| 76 | +The body has the details of the request or response. In a request, it can also |
| 77 | +be absent or be an empty map. Both these states will be interpreted equally. |
| 78 | +Responses will contain the body anyway even for an |
| 79 | +:ref:`IPROTO_PING <box_protocol-ping>` request, where it will be an empty MP_MAP. |
| 80 | + |
| 81 | +A lot of responses contain the IPROTO_DATA map: |
| 82 | + |
| 83 | +.. raw:: html |
| 84 | + :file: images/body.svg |
| 85 | + |
| 86 | +For most data-access requests (:ref:`IPROTO_SELECT <box_protocol-select>`, |
| 87 | +:ref:`IPROTO_INSERT <box_protocol-insert>`, :ref:`IPROTO_DELETE <box_protocol-delete>`, etc.) |
| 88 | +the body is an IPROTO_DATA map with an array of tuples that contain an array of fields. |
| 89 | + |
| 90 | +IPROTO_DATA is what we get with net_box and :ref:`Module buffer <buffer-module>` |
| 91 | +so if we were using net_box we could decode with |
| 92 | +:ref:`msgpack.decode_unchecked() <msgpack-decode_unchecked_string>`, |
| 93 | +or we could convert to a string with :samp:`ffi.string({pointer},{length})`. |
| 94 | +The :ref:`pickle.unpack() <pickle-unpack>` function might also be helpful. |
| 95 | + |
| 96 | +.. note:: |
| 97 | + |
| 98 | + For SQL-specific requests and responses, the body is a bit different. |
| 99 | + :ref:`Learn more <internals-iproto-sql>` about this type of packets. |
| 100 | + |
| 101 | +.. _box_protocol-responses_error: |
| 102 | + |
| 103 | +Error responses |
| 104 | +--------------- |
| 105 | + |
| 106 | +Instead of :ref:`IPROTO_OK <internals-iproto-ok>`, an error response header |
| 107 | +has IPROTO_REQUEST_TYPE = :ref:`IPROTO_TYPE_ERROR <internals-iproto-type_error>`. |
| 108 | +Its code is ``0x8XXX``, where ``XXX`` is the error code -- a value in |
| 109 | +`src/box/errcode.h <https://github.com/tarantool/tarantool/blob/master/src/box/errcode.h>`_. |
| 110 | +``src/box/errcode.h`` also has some convenience macros which define hexadecimal |
| 111 | +constants for return codes. |
| 112 | + |
| 113 | +The error response body is a map that contains two keys: :ref:`IPROTO_ERROR <internals-iproto-keys-error>` |
| 114 | +and :ref:`IPROTO_ERROR_24 <internals-iproto-keys-error>`. |
| 115 | +While IPROTO_ERROR contains an MP_EXT value, IPROTO_ERROR_24 contains a string. |
| 116 | +The two keys are provided to accommodate clients with older and newer Tarantool versions. |
| 117 | + |
| 118 | +.. raw:: html |
| 119 | + :file: images/error.svg |
| 120 | + |
| 121 | +Error responses before 2.4.1 |
| 122 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 123 | + |
| 124 | +Before Tarantool v. :doc:`2.4.1 </release/2.4.1>`, the key IPROTO_ERROR contained a string |
| 125 | +and was identical to the current IPROTO_ERROR_24 key. |
| 126 | + |
| 127 | +Let's consider an example. This is the fifth message, and the request was to create a duplicate |
| 128 | +space with ``conn:eval([[box.schema.space.create('_space');]])``. |
| 129 | +The unsuccessful response looks like this: |
| 130 | + |
| 131 | +.. raw:: html |
| 132 | + :file: images/error_24.svg |
| 133 | + |
| 134 | +The tutorial :ref:`Understanding the binary protocol <box_protocol-illustration>` |
| 135 | +shows actual byte codes of the response to the IPROTO_EVAL message. |
| 136 | + |
| 137 | +Looking in `errcode.h <https://github.com/tarantool/tarantool/blob/master/src/box/errcode.h>`__, |
| 138 | +we find that the error code ``0x0a`` (decimal 10) is |
| 139 | +ER_SPACE_EXISTS, and the string associated with ER_SPACE_EXISTS is |
| 140 | +"Space '%s' already exists". |
| 141 | + |
| 142 | +Since version :doc:`2.4.1 </release/2.4.1>`, responses for errors have extra information |
| 143 | +following what was described above. This extra information is given via the |
| 144 | +MP_ERROR extension type. See details in the :ref:`MessagePack extensions |
| 145 | +<msgpack_ext-error>` section. |
0 commit comments